0

Good morning,

What I want to do: I have the following xml (it's a part of the xml, not the complete)

<?xml version="1.0" encoding="UTF-8" ?>
<tv generator-info-name="Takealug EPG Grabber Ver. 1.1.2+matrix" generator-info-url="https://github.com/DeBaschdi/service.takealug.epg-grabber">

<!--  CHANNEL LIST -->
<channel id="Warner TV Film">
        <display-name lang="ch">Warner TV Film</display-name>
    </channel>
    <channel id="Warner TV Serie HD">
        <display-name lang="de">Warner TV Serie HD</display-name>
    </channel>

<!--  PROGRAMME LIST -->
   <programme start="20220111114500 +0000" stop="20220111143500 +0000" channel="Warner TV Film">
        <title lang="ch">Der Soldat James Ryan</title>
        <desc lang="ch">(US) 1997 • FSK 16 • IMDb:★★★★☆
        Captain John Miller soll den Soldaten James Ryan finden und lebend in Sicherheit bringen, um seiner Mutter den letzten Sohn zu retten.</desc>
        <date>1997</date>
        <category lang="ch">Adventure / Western / War</category>
        <country>US</country>
        <rating>
            <value>16</value>
        </rating>
        <star-rating system="IMDb">
            <value>8.6/10</value>
        </star-rating>
    </programme>

    <programme start="20220112222500 +0000" stop="20220112231500 +0000" channel="Warner TV Serie HD">
        <title lang="de">Lethal Weapon</title>
        <sub-title lang="de">Mein Plan, dein Plan</sub-title>
        <desc lang="de"> 2016 • S1 E3 • FSK 12
        Riggs und Murtaugh bekommen es mit einem Drogenkartell zu tun. Wie es scheint, ist auch Murtaughs ehemaliger Ausbilder Ned Brower in die Geschichte verwickelt. Als der Fall zu schwierig für sie wird, holt das Duo ihren Kollegen Cruz als Verstärkung an Bord. Riggs kommt nicht mit Mirandas Tod zurecht, während Murtaugh und Trish Probleme haben, einmal Zeit für Zweisamkeit zu finden.</desc>
        <date>2016</date>
        <category lang="de">Drama (Serie)</category>
        <category lang="de">Action</category>
        <episode-num system="onscreen">S1 E3</episode-num>
        <rating>
            <value>12</value>
        </rating>
    </programme>
</tv>

What i wanted to have as output:

<tv generator-info-name="Takealug EPG Grabber Ver. 1.1.2+matrix"
    generator-info-url="https://github.com/DeBaschdi/service.takealug.epg-grabber"><!--  CHANNEL LIST -->
   <channel id="Warner TV Film">
      <display-name lang="ch">Warner TV Film</display-name>
   </channel>
   <channel id="Warner TV Serie HD">
      <display-name lang="de">Warner TV Serie HD</display-name>
   </channel>
   <!--  PROGRAMME LIST -->
   <programme start="20220111114500 +0000"
              stop="20220111143500 +0000"
              channel="Warner TV Film">
      <sub-title>Adventure / Western / War | 1997 | US | FSK:+16</sub-title>
      <title lang="ch">Der Soldat James Ryan</title>
      <desc lang="ch">(US) 1997 • FSK 16 • IMDb:★★★★☆
        Captain John Miller soll den Soldaten James Ryan finden und lebend in Sicherheit bringen, um seiner Mutter den letzten Sohn zu retten.</desc>
      <rating>
         <value>16</value>
      </rating>
      <star-rating system="IMDb">
         <value>8.6/10</value>
      </star-rating>
   </programme>
   <programme start="20220112222500 +0000"
              stop="20220112231500 +0000"
              channel="Warner TV Serie HD">
      <sub-title>S1 E3 | Drama (Serie) | Action | 2016 | FSK:+12</sub-title>
      <title lang="de">Lethal Weapon: Mein Plan, dein Plan</title>
      <desc lang="de"> 2016 • S1 E3 • FSK 12
        Riggs und Murtaugh bekommen es mit einem Drogenkartell zu tun. Wie es scheint, ist auch Murtaughs ehemaliger Ausbilder Ned Brower in die Geschichte verwickelt. Als der Fall zu schwierig für sie wird, holt das Duo ihren Kollegen Cruz als Verstärkung an Bord. Riggs kommt nicht mit Mirandas Tod zurecht, während Murtaugh und Trish Probleme haben, einmal Zeit für Zweisamkeit zu finden.</desc>
      <rating>
         <value>12</value>
      </rating>
   </programme>
</tv>

So what i wantes is to have the elements title and sub-title merged. And the elements episode-num, category, date, rating - combined as new element sub-title.

What i tried:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <!-- IDENTITY TRANSFORM -->
    <xsl:template match="node()|@*">  
        <xsl:copy> 
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    
    <!-- REWRITE PROGRAMME -->
    
    <xsl:template match="programme"> 
        <xsl:copy>     
            <xsl:copy-of select="@*"/>
            <title><xsl:value-of select="concat(title, ' ', sub-title)" /></title>
            <xsl:apply-templates select="*[name()!='title' and name()!='sub-title']" /> 
        </xsl:copy>       
    </xsl:template>

      <xsl:template match="programme"> 
        <xsl:copy>    
            <xsl:copy-of select="@*"/>
            <sub-title><xsl:value-of select="episode-num, category, date, country" separator=" | "/><xsl:text> | FSK:+</xsl:text> <xsl:value-of select="rating/value"/></sub-title>
            <xsl:apply-templates select="*[name()!='episode-num' and name()!='category'and name()!='date' and name()!='country']"/>
        </xsl:copy>      
    </xsl:template>
       
</xsl:stylesheet>

Thats what i get as output:

<tv generator-info-name="Takealug EPG Grabber Ver. 1.1.2+matrix"
    generator-info-url="https://github.com/DeBaschdi/service.takealug.epg-grabber">

<!--  CHANNEL LIST -->

   <channel id="Warner TV Film">
      <display-name lang="ch">Warner TV Film</display-name>
   </channel>
   <channel id="Warner TV Serie HD">
      <display-name lang="de">Warner TV Serie HD</display-name>
   </channel>

   <!--  PROGRAMME LIST -->

   <programme start="20220111114500 +0000"
              stop="20220111143500 +0000"
              channel="Warner TV Film">
      <sub-title>Adventure / Western / War | 1997 | US | FSK:+16</sub-title>
      <title lang="ch">Der Soldat James Ryan</title>
      <desc lang="ch">(US) 1997 • FSK 16 • IMDb:★★★★☆
        Captain John Miller soll den Soldaten James Ryan finden und lebend in Sicherheit bringen, um seiner Mutter den letzten Sohn zu retten.</desc>
      <rating>
         <value>16</value>
      </rating>
   </programme>
   <programme start="20220112222500 +0000"
              stop="20220112231500 +0000"
              channel="Warner TV Serie HD">
      <sub-title>S1 E3 | Drama (Serie) | Action | 2016 | FSK:+12</sub-title>
      <title lang="de">Lethal Weapon</title>
      <sub-title lang="de">Mein Plan, dein Plan</sub-title>
      <desc lang="de"> 2016 • S1 E3 • FSK 12
        Riggs und Murtaugh bekommen es mit einem Drogenkartell zu tun. Wie es scheint, ist auch Murtaughs ehemaliger Ausbilder Ned Brower in die Geschichte verwickelt. Als der Fall zu schwierig für sie wird, holt das Duo ihren Kollegen Cruz als Verstärkung an Bord. Riggs kommt nicht mit Mirandas Tod zurecht, während Murtaugh und Trish Probleme haben, einmal Zeit für Zweisamkeit zu finden.</desc>
      <rating>
         <value>12</value>
      </rating>
   </programme>
</tv>

I tried some things (f.e. changed the order of the input) but i am not able to create an xsl where both changes (sub-title -> title AND episode-num,category,date,rating ->sub-title) get implemented. I am not sure what is my fallacy? Hopefully someone could help me, please. Thaaanks in advance :-)

Asperi
  • 228,894
  • 20
  • 464
  • 690
Alex Mutschl
  • 27
  • 1
  • 7
  • Which XSLT version can you use? Your stylesheet says `version="1.0"` but `` requires XSLT 2.0 or higher. – michael.hor257k Jan 14 '22 at 13:28
  • Hello, sorry I only used xsltransform.net until now, to test if it works and there worked also the separator-command, so i didn't realize that it requires XSLT 2.0. As I can't find any relatevely command for xslt 1.0 it would be easier to use xslt 2.0 instead? thanks for your help and don't blame me, as these are my first days with those things :-) – Alex Mutschl Jan 14 '22 at 14:47
  • The question is which processor will you be using in production. If it supports XSLT 2.0, then of course your code can take advantage of that. Otherwise you need to re-write for XSLT 1.0. – michael.hor257k Jan 14 '22 at 14:52
  • ok, I understand what you mean, thanks. I just posted a solution for xslt 1.0 as answer, but I want to give the XSLT 2.0 version a try. It seems easier. I will post my xslt 2.0 code in the next days when I have a bit more time. Maybe you can take a look at it then.. would be great. – Alex Mutschl Jan 14 '22 at 22:07
  • Even in XSLT 1.0 there is a more elegant approach. But first find out if you can use XSLT 2.0. – michael.hor257k Jan 14 '22 at 22:10
  • I will post my xslt 2.0 code in the next days when I have a bit more time. Maybe you can take a look at it then.. would be great. Oh ok - I will read further into xslt 1.0. Maybe I will find out – Alex Mutschl Jan 14 '22 at 22:14
  • I think you misunderstand me. You already have a working XSLT 2.0 code. The question is whether the XSLT processor that you will eventually use supports XSLT 2.0 or not. See here how to find out: https://stackoverflow.com/a/25245033/3016153 – michael.hor257k Jan 15 '22 at 01:33
  • i did understand you... XSLT 2.0 is also working. But as I said I am trying to learn and understand better all those xslt things, thats why I want to get also a working code for xslt 1.0 :-) I'm gettin nearer and nearer to my wanted output - there is onyl one little thing that's still not working. I posted a answer with my modified code - and with my hopefully last, small problem.. Maybe you can give me a hint to solve also this problem :-) – Alex Mutschl Jan 16 '22 at 22:15

2 Answers2

0

There are many ways this could be done, but here is a solution :

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <!-- IDENTITY TRANSFORM -->
    <xsl:template match="node()|@*">  
        <xsl:copy> 
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    
    <!-- Replace title value with concatenation of title and sub-title -->
    <xsl:template match="programme/title"> 
        <xsl:copy>
            <!-- If sub-title exists, concatenate with title. Else output title as-is. -->
            <xsl:choose>
              <xsl:when test="../sub-title">
                <xsl:value-of select="concat(., ' ', ../sub-title)"/>
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="."/>
              </xsl:otherwise>
            </xsl:choose>
        </xsl:copy>
        <!-- Insert new sub-title element -->
        <sub-title>
          <xsl:value-of select="concat(../episode-num, ' ', ../category, ' ', ../date, ' ', ../country)"/>
        </sub-title>
    </xsl:template>
    
    <!-- Remove original sub-title element -->
    <xsl:template match="programme/sub-title"/>
       
</xsl:stylesheet>

See it working here : https://xsltfiddle.liberty-development.net/6qjt5Rv

Sebastien
  • 2,672
  • 1
  • 8
  • 13
  • Hello, thanks for your suggestion. The only problem I got now is: I want to use a delimiter symbol (f.e. | ) between the different element like category, date etc. - When i set now, ' | ' , instead of, ' ', - and I have a movie as programme which has no episode-num it shows me the symbol | at the beginning - (also there is some programme which has no rating, so the symbol | is shown at the end). Thats no really looking good. So the separator-command would be the solution for this problem, but as I understood now it is not working for XSL 1.0 - Maybe you have an alternative way for this? – Alex Mutschl Jan 14 '22 at 15:08
  • @AlexMutschl you could do it with xsl:choose in which you check if each element is present and add the separator if it is. Like I did for building the concatenation of title and sub-title in the code I posted. – Sebastien Jan 14 '22 at 15:21
  • i posted an answer how I was able to solve my problem with " | " When I want do add also the element "rating" to sub-title, I had to do the same for "rating", right? (But probably its better to create a new question about this issue. Or maybe I will find a solution by myself) – Alex Mutschl Jan 14 '22 at 21:53
  • sorry for double post, but I just saw that my "solution" is only working when there is an element sub-title at ..... otherwise not. Some hint how to solve this? – Alex Mutschl Jan 14 '22 at 22:28
0

i did this, additionaly to your code for concetanating from title and sub-title: (I had to remove this code:

<!-- Remove original sub-title element -->
<xsl:template match="programme/sub-title"/> 

to get the right output.

<!-- IDENTITY TRANSFORM -->
<xsl:template match="node()|@*"> 
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
</xsl:template>

<!-- Replace title value with concatenation of title and sub-title -->

<xsl:template match="programme/title">
    <xsl:copy>

        <!-- If sub-title exists, concatenate with title. Else output title as-is. -->

        <xsl:choose>
          <xsl:when test="../sub-title">
            <xsl:value-of select="concat(., ': ', ../sub-title)"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="."/>
          </xsl:otherwise>
        </xsl:choose>
    </xsl:copy>
</xsl:template>

    <!-- Insert new sub-title element -->

<xsl:template match="programme/sub-title">
    <xsl:copy>
        <xsl:choose>
          <xsl:when test="../episode-num">
            <xsl:value-of select="concat(../episode-num, ' | ', ../category, ' | ', ../date, ' | ', ../country)"/>
          </xsl:when>
         <xsl:otherwise>
             <xsl:value-of select="concat(../category, ' | ', ../date, ' | ', ../country)"/>
         </xsl:otherwise>
        </xsl:choose>         
    </xsl:copy>
</xsl:template>
Peter Csala
  • 17,736
  • 16
  • 35
  • 75
Alex Mutschl
  • 27
  • 1
  • 7