From ee6f69af119e9cb75935926756cb0cebd4b9f2fc Mon Sep 17 00:00:00 2001
From: Pavel Kirilin <win10@list.ru>
Date: Sun, 15 Dec 2019 19:55:15 +0400
Subject: [PATCH] Added json, xml, xslt api support.

Signed-off-by: Pavel Kirilin <win10@list.ru>
---
 pom.xml                                       |   4 +
 .../controllers/controllerUtils.kt            |  37 +++++-
 .../rest/json/CinemasJsonController.kt        |  31 +++++
 .../rest/json/TicketsJsonController.kt        |  31 +++++
 .../rest/json/UsersJsonController.kt          |  31 +++++
 .../rest/xml/CinemasXmlController.kt          |  31 +++++
 .../rest/xml/TicketsXmlController.kt          |  30 +++++
 .../rest/xml/UsersXmlController.kt            |  30 +++++
 .../rest/xslt/CinemasXsltController.kt        |  33 ++++++
 .../rest/xslt/TicketsXsltController.kt        |  33 ++++++
 .../rest/xslt/UsersXsltController.kt          |  33 ++++++
 .../com/s3ai/corporate_app2/entities.kt       |  12 ++
 src/main/resources/xslt/cinema-process.xslt   |  59 ++++++++++
 src/main/resources/xslt/ticket-process.xslt   | 108 ++++++++++++++++++
 src/main/resources/xslt/user-process.xslt     |  51 +++++++++
 15 files changed, 552 insertions(+), 2 deletions(-)
 create mode 100644 src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/json/CinemasJsonController.kt
 create mode 100644 src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/json/TicketsJsonController.kt
 create mode 100644 src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/json/UsersJsonController.kt
 create mode 100644 src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xml/CinemasXmlController.kt
 create mode 100644 src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xml/TicketsXmlController.kt
 create mode 100644 src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xml/UsersXmlController.kt
 create mode 100644 src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xslt/CinemasXsltController.kt
 create mode 100644 src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xslt/TicketsXsltController.kt
 create mode 100644 src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xslt/UsersXsltController.kt
 create mode 100644 src/main/resources/xslt/cinema-process.xslt
 create mode 100644 src/main/resources/xslt/ticket-process.xslt
 create mode 100644 src/main/resources/xslt/user-process.xslt

diff --git a/pom.xml b/pom.xml
index 59c500a..3bdd527 100644
--- a/pom.xml
+++ b/pom.xml
@@ -40,6 +40,10 @@
             <groupId>com.fasterxml.jackson.module</groupId>
             <artifactId>jackson-module-kotlin</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.dataformat</groupId>
+            <artifactId>jackson-dataformat-xml</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-devtools</artifactId>
diff --git a/src/main/kotlin/com/s3ai/corporate_app2/controllers/controllerUtils.kt b/src/main/kotlin/com/s3ai/corporate_app2/controllers/controllerUtils.kt
index 74018cd..1ae2e7b 100644
--- a/src/main/kotlin/com/s3ai/corporate_app2/controllers/controllerUtils.kt
+++ b/src/main/kotlin/com/s3ai/corporate_app2/controllers/controllerUtils.kt
@@ -1,9 +1,16 @@
 package com.s3ai.corporate_app2.controllers
 
+import com.fasterxml.jackson.dataformat.xml.XmlMapper
 import com.s3ai.corporate_app2.CinemaServices
-import org.springframework.ui.Model
+import org.springframework.util.ResourceUtils
+import java.io.StringReader
+import java.io.StringWriter
 import java.util.*
 import javax.servlet.http.HttpServletResponse
+import javax.xml.transform.TransformerFactory
+import javax.xml.transform.stream.StreamResult
+import javax.xml.transform.stream.StreamSource
+
 
 fun <T> deleteInstance(id: String, instanceName: String, jpaService: CinemaServices<T>, response: HttpServletResponse): String? {
     var responseString: String? = null
@@ -20,4 +27,30 @@ fun <T> deleteInstance(id: String, instanceName: String, jpaService: CinemaServi
         responseString = e.localizedMessage
     }
     return responseString
-}
\ No newline at end of file
+}
+
+fun <T> getInstance(id: UUID, jpaService: CinemaServices<T>, response: HttpServletResponse): T? {
+    val item = jpaService.findById(id)
+    if (null != item) return item
+    else response.status = HttpServletResponse.SC_NOT_FOUND
+    return null
+}
+
+fun XMLTransform(item: Any, resource_name: String): String {
+    val xmlMapper = XmlMapper()
+    val xslt = StreamSource(ResourceUtils.getFile("classpath:xslt/$resource_name"))
+    val xml = StreamSource(StringReader(xmlMapper.writeValueAsString(item)))
+    val transformer = TransformerFactory.newInstance().newTransformer(xslt)
+    val sw = StringWriter()
+    transformer.transform(xml, StreamResult(sw))
+    return sw.toString()
+}
+
+fun <T> getXSLTransformedInstance(id: UUID, jpaService: CinemaServices<T>, resource_name: String, response: HttpServletResponse): String {
+    val item = jpaService.findById(id)
+    if (null == item) response.status = HttpServletResponse.SC_NOT_FOUND
+    else {
+        return XMLTransform(item, resource_name)
+    }
+    return ""
+}
diff --git a/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/json/CinemasJsonController.kt b/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/json/CinemasJsonController.kt
new file mode 100644
index 0000000..033ea39
--- /dev/null
+++ b/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/json/CinemasJsonController.kt
@@ -0,0 +1,31 @@
+package com.s3ai.corporate_app2.controllers.rest.json
+
+import com.s3ai.corporate_app2.Cinema
+import com.s3ai.corporate_app2.CinemaService
+import com.s3ai.corporate_app2.controllers.getInstance
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.MediaType
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.PathVariable
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+import java.util.*
+import javax.servlet.http.HttpServletResponse
+
+@RestController
+@RequestMapping("/api/json/cinemas/")
+class CinemasJsonController {
+    @Autowired
+    lateinit var cinemaService: CinemaService
+
+    @GetMapping("/all", produces = [MediaType.APPLICATION_JSON_VALUE])
+    fun getCinemas(response: HttpServletResponse): MutableList<Cinema> {
+        return cinemaService.findAll()
+    }
+
+    @GetMapping("/item/{id}", produces = [MediaType.APPLICATION_JSON_VALUE])
+    fun getCinema(@PathVariable id: UUID, response: HttpServletResponse): Cinema? {
+        return getInstance(id, cinemaService, response)
+    }
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/json/TicketsJsonController.kt b/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/json/TicketsJsonController.kt
new file mode 100644
index 0000000..12e7eec
--- /dev/null
+++ b/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/json/TicketsJsonController.kt
@@ -0,0 +1,31 @@
+package com.s3ai.corporate_app2.controllers.rest.json
+
+import com.s3ai.corporate_app2.Ticket
+import com.s3ai.corporate_app2.TicketService
+import com.s3ai.corporate_app2.controllers.getInstance
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.MediaType
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.PathVariable
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+import java.util.*
+import javax.servlet.http.HttpServletResponse
+
+@RestController
+@RequestMapping("/api/json/tickets/")
+class TicketsJsonController {
+    @Autowired
+    lateinit var ticketService: TicketService
+
+    @GetMapping("/all", produces = [MediaType.APPLICATION_JSON_VALUE])
+    fun getTickets(response: HttpServletResponse): MutableList<Ticket> {
+        return ticketService.findAll()
+    }
+
+    @GetMapping("/item/{id}", produces = [MediaType.APPLICATION_JSON_VALUE])
+    fun getTicket(@PathVariable id: UUID, response: HttpServletResponse): Ticket? {
+        return getInstance(id, ticketService, response)
+    }
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/json/UsersJsonController.kt b/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/json/UsersJsonController.kt
new file mode 100644
index 0000000..72cb67d
--- /dev/null
+++ b/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/json/UsersJsonController.kt
@@ -0,0 +1,31 @@
+package com.s3ai.corporate_app2.controllers.rest.json
+
+import com.s3ai.corporate_app2.User
+import com.s3ai.corporate_app2.UserService
+import com.s3ai.corporate_app2.controllers.getInstance
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.MediaType
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.PathVariable
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+import java.util.*
+import javax.servlet.http.HttpServletResponse
+
+@RestController
+@RequestMapping("/api/json/users/")
+class UsersJsonController {
+    @Autowired
+    lateinit var userService: UserService
+
+    @GetMapping("/all", produces = [MediaType.APPLICATION_JSON_VALUE])
+    fun getUsers(response: HttpServletResponse): MutableList<User> {
+        return userService.findAll()
+    }
+
+    @GetMapping("/item/{id}", produces = [MediaType.APPLICATION_JSON_VALUE])
+    fun getUser(@PathVariable id: UUID, response: HttpServletResponse): User? {
+        return getInstance(id, userService, response)
+    }
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xml/CinemasXmlController.kt b/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xml/CinemasXmlController.kt
new file mode 100644
index 0000000..c566429
--- /dev/null
+++ b/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xml/CinemasXmlController.kt
@@ -0,0 +1,31 @@
+package com.s3ai.corporate_app2.controllers.rest.xml
+
+import com.s3ai.corporate_app2.Cinema
+import com.s3ai.corporate_app2.CinemaService
+import com.s3ai.corporate_app2.controllers.getInstance
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.MediaType
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.PathVariable
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+import java.util.*
+import javax.servlet.http.HttpServletResponse
+
+@RestController
+@RequestMapping("/api/xml/cinemas/")
+class CinemasXmlController {
+    @Autowired
+    lateinit var cinemaService: CinemaService
+
+    @GetMapping("/all", produces = [MediaType.APPLICATION_XML_VALUE])
+    fun getCinemas(response: HttpServletResponse): MutableList<Cinema> {
+        return cinemaService.findAll()
+    }
+
+    @GetMapping("/item/{id}", produces = [MediaType.APPLICATION_XML_VALUE])
+    fun getCinema(@PathVariable id: UUID, response: HttpServletResponse): Cinema? {
+        return getInstance(id, cinemaService, response)
+    }
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xml/TicketsXmlController.kt b/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xml/TicketsXmlController.kt
new file mode 100644
index 0000000..ddd5b79
--- /dev/null
+++ b/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xml/TicketsXmlController.kt
@@ -0,0 +1,30 @@
+package com.s3ai.corporate_app2.controllers.rest.xml
+
+import com.s3ai.corporate_app2.Ticket
+import com.s3ai.corporate_app2.TicketService
+import com.s3ai.corporate_app2.controllers.getInstance
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.MediaType
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.PathVariable
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+import java.util.*
+import javax.servlet.http.HttpServletResponse
+
+@RestController
+@RequestMapping("/api/xml/tickets/")
+class TicketsXmlController {
+    @Autowired
+    lateinit var ticketService: TicketService
+
+    @GetMapping("/all", produces = [MediaType.APPLICATION_XML_VALUE])
+    fun getTickets(response: HttpServletResponse): MutableList<Ticket> {
+        return ticketService.findAll()
+    }
+
+    @GetMapping("/item/{id}", produces = [MediaType.APPLICATION_XML_VALUE])
+    fun getTicket(@PathVariable id: UUID, response: HttpServletResponse): Ticket? {
+        return getInstance(id, ticketService, response)
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xml/UsersXmlController.kt b/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xml/UsersXmlController.kt
new file mode 100644
index 0000000..4de521b
--- /dev/null
+++ b/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xml/UsersXmlController.kt
@@ -0,0 +1,30 @@
+package com.s3ai.corporate_app2.controllers.rest.xml
+
+import com.s3ai.corporate_app2.User
+import com.s3ai.corporate_app2.UserService
+import com.s3ai.corporate_app2.controllers.getInstance
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.MediaType
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.PathVariable
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+import java.util.*
+import javax.servlet.http.HttpServletResponse
+
+@RestController
+@RequestMapping("/api/xml/users/")
+class UsersXmlController {
+    @Autowired
+    lateinit var userService: UserService
+
+    @GetMapping("/all", produces = [MediaType.APPLICATION_XML_VALUE])
+    fun getUsers(response: HttpServletResponse): MutableList<User> {
+        return userService.findAll()
+    }
+
+    @GetMapping("/item/{id}", produces = [MediaType.APPLICATION_XML_VALUE])
+    fun getUser(@PathVariable id: UUID, response: HttpServletResponse): User? {
+        return getInstance(id, userService, response)
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xslt/CinemasXsltController.kt b/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xslt/CinemasXsltController.kt
new file mode 100644
index 0000000..498cd0a
--- /dev/null
+++ b/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xslt/CinemasXsltController.kt
@@ -0,0 +1,33 @@
+package com.s3ai.corporate_app2.controllers.rest.xslt
+
+import com.s3ai.corporate_app2.CinemaService
+import com.s3ai.corporate_app2.controllers.XMLTransform
+import com.s3ai.corporate_app2.controllers.getXSLTransformedInstance
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.MediaType
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.PathVariable
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+import java.util.*
+import javax.servlet.http.HttpServletResponse
+
+@RestController
+@RequestMapping("/api/xslt/cinemas/")
+class CinemasXsltController {
+    @Autowired
+    lateinit var cinemaService: CinemaService
+
+    val xsltResourceName: String = "cinema-process.xslt"
+
+    @GetMapping("/all", produces = [MediaType.TEXT_HTML_VALUE])
+    fun getCinemas(response: HttpServletResponse): String {
+        return XMLTransform(cinemaService.findAll(), xsltResourceName)
+    }
+
+
+    @GetMapping("/item/{id}", produces = [MediaType.TEXT_HTML_VALUE])
+    fun getCinema(@PathVariable id: UUID, response: HttpServletResponse): String? {
+        return getXSLTransformedInstance(id, cinemaService, xsltResourceName, response)
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xslt/TicketsXsltController.kt b/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xslt/TicketsXsltController.kt
new file mode 100644
index 0000000..896eca4
--- /dev/null
+++ b/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xslt/TicketsXsltController.kt
@@ -0,0 +1,33 @@
+package com.s3ai.corporate_app2.controllers.rest.xslt
+
+import com.s3ai.corporate_app2.TicketService
+import com.s3ai.corporate_app2.controllers.XMLTransform
+import com.s3ai.corporate_app2.controllers.getXSLTransformedInstance
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.MediaType
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.PathVariable
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+import java.util.*
+import javax.servlet.http.HttpServletResponse
+
+@RestController
+@RequestMapping("/api/xslt/tickets/")
+class TicketsXsltController {
+    @Autowired
+    lateinit var ticketService: TicketService
+
+    val xsltResourceName: String = "ticket-process.xslt"
+
+    @GetMapping("/all", produces = [MediaType.TEXT_HTML_VALUE])
+    fun getCinemas(response: HttpServletResponse): String {
+        return XMLTransform(ticketService.findAll(), xsltResourceName)
+    }
+
+
+    @GetMapping("/item/{id}", produces = [MediaType.TEXT_HTML_VALUE])
+    fun getCinema(@PathVariable id: UUID, response: HttpServletResponse): String? {
+        return getXSLTransformedInstance(id, ticketService, xsltResourceName, response)
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xslt/UsersXsltController.kt b/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xslt/UsersXsltController.kt
new file mode 100644
index 0000000..f07ee83
--- /dev/null
+++ b/src/main/kotlin/com/s3ai/corporate_app2/controllers/rest/xslt/UsersXsltController.kt
@@ -0,0 +1,33 @@
+package com.s3ai.corporate_app2.controllers.rest.xslt
+
+import com.s3ai.corporate_app2.UserService
+import com.s3ai.corporate_app2.controllers.XMLTransform
+import com.s3ai.corporate_app2.controllers.getXSLTransformedInstance
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.MediaType
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.PathVariable
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+import java.util.*
+import javax.servlet.http.HttpServletResponse
+
+@RestController
+@RequestMapping("/api/xslt/users/")
+class UsersXsltController {
+    @Autowired
+    lateinit var userService: UserService
+
+    val xsltResourceName: String = "user-process.xslt"
+
+    @GetMapping("/all", produces = [MediaType.TEXT_HTML_VALUE])
+    fun getCinemas(response: HttpServletResponse): String {
+        return XMLTransform(userService.findAll(), xsltResourceName)
+    }
+
+
+    @GetMapping("/item/{id}", produces = [MediaType.TEXT_HTML_VALUE])
+    fun getCinema(@PathVariable id: UUID, response: HttpServletResponse): String? {
+        return getXSLTransformedInstance(id, userService, xsltResourceName, response)
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/s3ai/corporate_app2/entities.kt b/src/main/kotlin/com/s3ai/corporate_app2/entities.kt
index c84b767..28ceb6d 100644
--- a/src/main/kotlin/com/s3ai/corporate_app2/entities.kt
+++ b/src/main/kotlin/com/s3ai/corporate_app2/entities.kt
@@ -1,21 +1,30 @@
 package com.s3ai.corporate_app2
 
+import com.fasterxml.jackson.annotation.JsonAutoDetect
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement
 import org.hibernate.annotations.OnDelete
 import org.hibernate.annotations.OnDeleteAction
 import java.util.*
 import javax.persistence.*
+import javax.xml.bind.annotation.XmlRootElement
 
 @Entity
 @Table(name = "cinema")
+@XmlRootElement(name = "Cinema")
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
 class Cinema {
     @Id
     @Column(name = "ID")
     @GeneratedValue(strategy = GenerationType.AUTO)
     var id: UUID? = null
+
     @Column(name = "name")
     var name: String? = null
+
     @Column(name = "seats_count")
     var seatsCount: Int? = null
+
     @Column(name = "location")
     var location: String? = null
 
@@ -27,6 +36,8 @@ class Cinema {
 
 @Entity
 @Table(name = "cinema_user")
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
+@XmlRootElement(name = "User")
 class User {
     @Id
     @Column(name = "ID")
@@ -44,6 +55,7 @@ class User {
 
 @Entity
 @Table(name = "ticket")
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
 class Ticket {
     @Id
     @Column(name = "ID")
diff --git a/src/main/resources/xslt/cinema-process.xslt b/src/main/resources/xslt/cinema-process.xslt
new file mode 100644
index 0000000..8af051d
--- /dev/null
+++ b/src/main/resources/xslt/cinema-process.xslt
@@ -0,0 +1,59 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+    <xsl:template match="/ArrayList">
+        <table>
+            <tr>
+                <th class="col">UUID</th>
+                <th class="col">Name</th>
+                <th class="col">Seats count</th>
+                <th class="col">Location</th>
+            </tr>
+            <xsl:apply-templates/>
+        </table>
+    </xsl:template>
+
+    <xsl:template match="item">
+        <tr>
+            <xsl:variable name="uuid" select="string(id)"/>
+            <td>
+                <a href="/api/xslt/cinemas/item/{$uuid}">
+                    <xsl:value-of select="string(id)"/>
+                </a>
+            </td>
+            <td>
+                <xsl:value-of select="string(name)"/>
+            </td>
+            <td>
+                <xsl:value-of select="string(seatsCount)"/>
+            </td>
+            <td>
+                <xsl:value-of select="string(location)"/>
+            </td>
+        </tr>
+    </xsl:template>
+
+    <xsl:template match="Cinema">
+        <div>
+            <a href="/api/xslt/cinemas/all">Go back to list</a>
+        </div>
+        <ul>
+            <li>
+                UUID:
+                <xsl:value-of select="string(id)"/>
+            </li>
+            <li>
+                Name:
+                <xsl:value-of select="string(name)"/>
+            </li>
+            <li>
+                Seats count:
+                <xsl:value-of select="string(seatsCount)"/>
+            </li>
+            <li>
+                Location:
+                <xsl:value-of select="string(location)"/>
+            </li>
+        </ul>
+    </xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/src/main/resources/xslt/ticket-process.xslt b/src/main/resources/xslt/ticket-process.xslt
new file mode 100644
index 0000000..6ad1328
--- /dev/null
+++ b/src/main/resources/xslt/ticket-process.xslt
@@ -0,0 +1,108 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+    <xsl:template match="/ArrayList">
+        <table>
+            <tr>
+                <th class="col">UUID</th>
+                <th class="col">Name</th>
+                <th class="col">Cinema id</th>
+                <th class="col">User id</th>
+            </tr>
+            <xsl:apply-templates/>
+        </table>
+    </xsl:template>
+
+    <xsl:template match="item">
+        <tr>
+            <xsl:variable name="uuid" select="string(id)"/>
+            <td>
+                <a href="/api/xslt/tickets/item/{$uuid}">
+                    <xsl:value-of select="string(id)"/>
+                </a>
+            </td>
+            <td>
+                <xsl:value-of select="string(movie)"/>
+            </td>
+            <xsl:variable name="cinema_id" select="string(cinema/id)"/>
+            <td>
+                <a href="/api/xslt/cinemas/item/{$cinema_id}">
+                    <xsl:value-of select="string(cinema/id)"/>
+                </a>
+            </td>
+            <xsl:variable name="user_id" select="string(user/id)"/>
+            <td>
+                <a href="/api/xslt/users/item/{$user_id}">
+                    <xsl:value-of select="string(user/id)"/>
+                </a>
+            </td>
+
+        </tr>
+    </xsl:template>
+
+    <xsl:template match="Ticket">
+        <div>
+            <a href="/api/xslt/tickets/all">Go back to list</a>
+        </div>
+        <ul>
+            <li>
+                UUID:
+                <xsl:value-of select="string(id)"/>
+            </li>
+            <li>
+                Movie:
+                <xsl:value-of select="string(movie)"/>
+            </li>
+            <li>
+                <xsl:apply-templates select="cinema"/>
+            </li>
+            <li>
+                <xsl:apply-templates select="user"/>
+            </li>
+
+        </ul>
+    </xsl:template>
+
+    <xsl:template match="cinema">
+        <p>Cinema:</p>
+        <ul>
+            <xsl:variable name="uuid" select="string(id)"/>
+            <li>
+                ID:
+                <a href="/api/xslt/cinemas/item/{$uuid}">
+                    <xsl:value-of select="string(id)"/>
+                </a>
+            </li>
+            <li>
+                Name:
+                <xsl:value-of select="string(name)"/>
+            </li>
+            <li>
+                Seats count:
+                <xsl:value-of select="string(seatsCount)"/>
+            </li>
+            <li>
+                Location:
+                <xsl:value-of select="string(location)"/>
+            </li>
+        </ul>
+    </xsl:template>
+
+    <xsl:template match="user">
+        <p>User:</p>
+        <ul>
+            <xsl:variable name="uuid" select="string(id)"/>
+            <li>
+                ID:
+                <a href="/api/xslt/users/item/{$uuid}">
+                    <xsl:value-of select="string(id)"/>
+                </a>
+            </li>
+            <li>
+                Name: <xsl:value-of select="string(name)"/>
+            </li>
+            <li>
+                Age: <xsl:value-of select="string(age)"/>
+            </li>
+        </ul>
+    </xsl:template>
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/src/main/resources/xslt/user-process.xslt b/src/main/resources/xslt/user-process.xslt
new file mode 100644
index 0000000..3834aa0
--- /dev/null
+++ b/src/main/resources/xslt/user-process.xslt
@@ -0,0 +1,51 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+    <xsl:template match="/ArrayList">
+        <table>
+            <tr>
+                <th class="col">UUID</th>
+                <th class="col">Name</th>
+                <th class="col">Age</th>
+            </tr>
+            <xsl:apply-templates/>
+        </table>
+    </xsl:template>
+
+    <xsl:template match="item">
+        <tr>
+            <xsl:variable name="uuid" select="string(id)"/>
+            <td>
+                <a href="/api/xslt/users/item/{$uuid}">
+                    <xsl:value-of select="string(id)"/>
+                </a>
+            </td>
+            <td>
+                <xsl:value-of select="string(name)"/>
+            </td>
+            <td>
+                <xsl:value-of select="string(age)"/>
+            </td>
+        </tr>
+    </xsl:template>
+
+    <xsl:template match="User">
+        <div>
+            <a href="/api/xslt/users/all">Go back to list</a>
+        </div>
+        <ul>
+            <li>
+                UUID:
+                <xsl:value-of select="string(id)"/>
+            </li>
+            <li>
+                Name:
+                <xsl:value-of select="string(name)"/>
+            </li>
+            <li>
+                Age:
+                <xsl:value-of select="string(age)"/>
+            </li>
+        </ul>
+    </xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file
-- 
GitLab