我必须将以下源文件转换为XML并根据class属性对元素进行排序。转换工作正常,但我无法应用基于class属性的排序,因此所有HD歌曲和SD歌曲都被分组。我尝试过xsl:perform-sort,但我不确定在XSLT中应用它的位置和方法。
这是我的源文件:
<html>
<head>
<title></title>
</head>
<body>
<!-- This is my first comment -->
<ol>
<li>3 Song 1</li>
<li>4 Song 2</li>
<li>5 Song 3</li>
<li>7 Song 4</li>
<li>8 Song 5</li>
<li>10 Song 6</li>
<li>14 Song 7</li>
<li>16 Song 8</li>
<li>18 Song 9</li>
<li>19 Song 10</li>
<li>26 Song 11</li>
<li>29 Song 12</li>
<li>31 Song 13</li>
<li>34 Song 14</li>
<li>37 Song 15</li>
<li>39 Song 16</li>
<li>41 Song 17</li>
<li>44 Song 18</li>
</ol>
</body>
</html>
这是我的XSLT 2.0:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xspf="http://xspf.org/ns/0/"
xmlns:vlc="http://www.videolan.org/vlc/playlist/ns/0/" version="2">
<xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
<!-- It is very important to add the prefix xspf to the xmlns for xspf otherwise the sorting does not work-->
<!--This identity transform template allows to copy the whole document and then drop all the parts that we don't want to keep-->
<xsl:template match="/">
<xsl:copy>
<xsl:apply-templates/>
<xsl:variable name="tracks">
<xsl:perform-sort select="trackList/track">
<xsl:sort select="title/@class" data-type="text" />
</xsl:perform-sort>
</xsl:variable>
<trackList>
<xsl:copy-of select="$tracks"/>
</trackList>
</xsl:copy>
</xsl:template>
<!-- Drop the content of the head, hr, and h1 elements -->
<xsl:template match="head|hr|h1"/>
<!--Copy the content of <ol> and its children-->
<xsl:template match="ol">
<!-- TrackList is case sensitive and it was not working without the proper-->
<trackList>
<xsl:apply-templates/>
</trackList>
</xsl:template>
<!--Copy the content of <li> and its content-->
<xsl:template name="mylist" match="li">
<!-- Create new elements track and title as its child and grab the current content of li text, then use the second group of string using tokenize() -->
<track>
<location>
<!-- The substring-before functionality allows to grab the first set of characters/word/number before the provided arg$, in this case space ' '-->
<xsl:value-of select="concat('http://localhost/auto/v',substring-before(., ' '),'?dlna')"
/>
</location>
<title>
<xsl:variable name="cleaned" select="replace(.,'\(HD\)|-DTV',' HD')"/>
<!-- Check if track title contains HD create a class for SD or HD for it -->
<xsl:choose>
<xsl:when test="contains($cleaned, 'HD')">
<xsl:attribute name="class">
<xsl:text>HD</xsl:text>
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="class">
<xsl:text>SD</xsl:text>
</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
<!-- Create a variable to hold the cleaned title for every track -->
<!--<xsl:value-of select="replace(.,'(HD)','HD',substring-after(., ' '))" />-->
<xsl:value-of select="substring-after($cleaned, ' ')"/>
</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>
<!-- Count the number of <li> as they represent a single track -->
<xsl:number count="li"/>
<!--<xsl:value-of select="substring-before(., ' ')"/>-->
</vlc:id>
</extension>
</track>
</xsl:template>
<!--Copy the content of <body> and its children. This snippet was at the beginning of the document, but then I moved it to the end of the XSLT-->
<xsl:template match="body">
<playlist>
<title>Playlist</title>
<xsl:apply-templates/>
<!-- By putting the apply-templates above this snippet it makes it generate after the whole document, which is what I wanted to achieve. -->
<!-- For every substring-before create a list of vlc:item as found in the automatically created VLC playlist-->
<extension application="http://www.videolan.org/vlc/playlist/0">
<xsl:for-each select="(ol/li/text())">
<!-- This allows to create self-closing attribute tag for vlc:id tid-->
<xsl:variable name="vlcname">
<xsl:value-of select="substring-before(., ' ')"/>
</xsl:variable>
<xsl:element name="vlc:item">
<xsl:attribute name="tid">
<!-- Count the number of <li> as they represent a single track -->
<xsl:number count="li" format="0"/>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</extension>
</playlist>
</xsl:template>
</xsl:stylesheet>
生成的XML应如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<playlist xmlns:xspf="http://xspf.org/ns/0/"
xmlns:vlc="http://www.videolan.org/vlc/playlist/ns/0/">
<title>Playlist</title>
<trackList>
<track>
<location>http://localhost/auto/v34?dlna</location>
<title class="HD">Song 14 HD</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>14</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v44?dlna</location>
<title class="HD">Song 18 HD</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>18</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v7?dlna</location>
<title class="HD">Song 4 HD</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>4</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v19?dlna</location>
<title class="HD">Song 10 HD</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>10</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v3?dlna</location>
<title class="SD">Song 1</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>1</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v4?dlna</location>
<title class="SD">Song 2</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>2</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v5?dlna</location>
<title class="SD">Song 3</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>3</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v8?dlna</location>
<title class="SD">Song 5</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>5</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v10?dlna</location>
<title class="SD">Song 6</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>6</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v14?dlna</location>
<title class="SD">Song 7</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>7</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v16?dlna</location>
<title class="SD">Song 8</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>8</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v18?dlna</location>
<title class="SD">Song 9</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>9</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v26?dlna</location>
<title class="SD">Song 11</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>11</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v29?dlna</location>
<title class="SD">Song 12</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>12</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v31?dlna</location>
<title class="SD">Song 13</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>13</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v37?dlna</location>
<title class="SD">Song 15</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>15</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v39?dlna</location>
<title class="SD">Song 16</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>16</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v41?dlna</location>
<title class="SD">Song 17</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>17</vlc:id>
</extension>
</track>
</trackList>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:item tid="1"/>
<vlc:item tid="2"/>
<vlc:item tid="3"/>
<vlc:item tid="4"/>
<vlc:item tid="5"/>
<vlc:item tid="6"/>
<vlc:item tid="7"/>
<vlc:item tid="8"/>
<vlc:item tid="9"/>
<vlc:item tid="10"/>
<vlc:item tid="11"/>
<vlc:item tid="12"/>
<vlc:item tid="13"/>
<vlc:item tid="14"/>
<vlc:item tid="15"/>
<vlc:item tid="16"/>
<vlc:item tid="17"/>
<vlc:item tid="18"/>
</extension>
</playlist>
答案 0 :(得分:1)
您需要对序列执行xsl:perform-sort
。我通过删除与/
匹配的模板并修改与ol
匹配的模板来略微修改了您的XSLT。 (并添加了xsl:strip-space
以获得更好看的输出。如果您的输入有重要的空格,可能需要删除它。)
XML输入(向HD
添加了一些li
)
<html>
<head>
<title></title>
</head>
<body>
<!-- This is my first comment -->
<ol>
<li>3 Song 1</li>
<li>4 Song 2</li>
<li>5 Song 3 HD</li>
<li>7 Song 4</li>
<li>8 Song 5</li>
<li>10 Song 6 HD</li>
<li>14 Song 7</li>
<li>16 Song 8</li>
<li>18 Song 9</li>
<li>19 Song 10 HD</li>
<li>26 Song 11</li>
<li>29 Song 12</li>
<li>31 Song 13 HD</li>
<li>34 Song 14</li>
<li>37 Song 15</li>
<li>39 Song 16</li>
<li>41 Song 17 HD</li>
<li>44 Song 18</li>
</ol>
</body>
</html>
更新了XSLT 2.0
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xspf="http://xspf.org/ns/0/"
xmlns:vlc="http://www.videolan.org/vlc/playlist/ns/0/" version="2">
<xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- It is very important to add the prefix xspf to the xmlns for xspf otherwise the sorting does not work-->
<!--This identity transform template allows to copy the whole document and then drop all the parts that we don't want to keep-->
<!-- Drop the content of the head, hr, and h1 elements -->
<xsl:template match="head|hr|h1"/>
<!--Copy the content of <ol> and its children-->
<xsl:template match="ol">
<!-- TrackList is case sensitive and it was not working without the proper-->
<trackList>
<xsl:variable name="tracks">
<xsl:apply-templates/>
</xsl:variable>
<xsl:perform-sort select="$tracks/*">
<xsl:sort select="title/@class"/>
</xsl:perform-sort>
</trackList>
</xsl:template>
<!--Copy the content of <li> and its content-->
<xsl:template name="mylist" match="li">
<!-- Create new elements track and title as its child and grab the current content of li text, then use the second group of string using tokenize() -->
<track>
<location>
<!-- The substring-before functionality allows to grab the first set of characters/word/number before the provided arg$, in this case space ' '-->
<xsl:value-of select="concat('http://localhost/auto/v',substring-before(., ' '),'?dlna')"
/>
</location>
<title>
<xsl:variable name="cleaned" select="replace(.,'\(HD\)|-DTV',' HD')"/>
<!-- Check if track title contains HD create a class for SD or HD for it -->
<xsl:choose>
<xsl:when test="contains($cleaned, 'HD')">
<xsl:attribute name="class">
<xsl:text>HD</xsl:text>
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="class">
<xsl:text>SD</xsl:text>
</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
<!-- Create a variable to hold the cleaned title for every track -->
<!--<xsl:value-of select="replace(.,'(HD)','HD',substring-after(., ' '))" />-->
<xsl:value-of select="substring-after($cleaned, ' ')"/>
</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>
<!-- Count the number of <li> as they represent a single track -->
<xsl:number count="li"/>
<!--<xsl:value-of select="substring-before(., ' ')"/>-->
</vlc:id>
</extension>
</track>
</xsl:template>
<!--Copy the content of <body> and its children. This snippet was at the beginning of the document, but then I moved it to the end of the XSLT-->
<xsl:template match="body">
<playlist>
<title>Playlist</title>
<xsl:apply-templates/>
<!-- By putting the apply-templates above this snippet it makes it generate after the whole document, which is what I wanted to achieve. -->
<!-- For every substring-before create a list of vlc:item as found in the automatically created VLC playlist-->
<extension application="http://www.videolan.org/vlc/playlist/0">
<xsl:for-each select="(ol/li/text())">
<!-- This allows to create self-closing attribute tag for vlc:id tid-->
<xsl:variable name="vlcname">
<xsl:value-of select="substring-before(., ' ')"/>
</xsl:variable>
<xsl:element name="vlc:item">
<xsl:attribute name="tid">
<!-- Count the number of <li> as they represent a single track -->
<xsl:number count="li" format="0"/>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</extension>
</playlist>
</xsl:template>
</xsl:stylesheet>
<强>输出强>
<playlist xmlns:xspf="http://xspf.org/ns/0/"
xmlns:vlc="http://www.videolan.org/vlc/playlist/ns/0/">
<title>Playlist</title>
<trackList>
<track>
<location>http://localhost/auto/v5?dlna</location>
<title class="HD">Song 3 HD</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>3</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v10?dlna</location>
<title class="HD">Song 6 HD</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>6</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v19?dlna</location>
<title class="HD">Song 10 HD</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>10</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v31?dlna</location>
<title class="HD">Song 13 HD</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>13</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v41?dlna</location>
<title class="HD">Song 17 HD</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>17</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v3?dlna</location>
<title class="SD">Song 1</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>1</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v4?dlna</location>
<title class="SD">Song 2</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>2</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v7?dlna</location>
<title class="SD">Song 4</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>4</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v8?dlna</location>
<title class="SD">Song 5</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>5</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v14?dlna</location>
<title class="SD">Song 7</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>7</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v16?dlna</location>
<title class="SD">Song 8</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>8</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v18?dlna</location>
<title class="SD">Song 9</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>9</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v26?dlna</location>
<title class="SD">Song 11</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>11</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v29?dlna</location>
<title class="SD">Song 12</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>12</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v34?dlna</location>
<title class="SD">Song 14</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>14</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v37?dlna</location>
<title class="SD">Song 15</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>15</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v39?dlna</location>
<title class="SD">Song 16</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>16</vlc:id>
</extension>
</track>
<track>
<location>http://localhost/auto/v44?dlna</location>
<title class="SD">Song 18</title>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:id>18</vlc:id>
</extension>
</track>
</trackList>
<extension application="http://www.videolan.org/vlc/playlist/0">
<vlc:item tid="1"/>
<vlc:item tid="2"/>
<vlc:item tid="3"/>
<vlc:item tid="4"/>
<vlc:item tid="5"/>
<vlc:item tid="6"/>
<vlc:item tid="7"/>
<vlc:item tid="8"/>
<vlc:item tid="9"/>
<vlc:item tid="10"/>
<vlc:item tid="11"/>
<vlc:item tid="12"/>
<vlc:item tid="13"/>
<vlc:item tid="14"/>
<vlc:item tid="15"/>
<vlc:item tid="16"/>
<vlc:item tid="17"/>
<vlc:item tid="18"/>
</extension>
</playlist>