XSLT列表转换

时间:2012-04-19 22:07:24

标签: xslt xslt-2.0

我目前正在开发一个XSL脚本,它将以下xml转换为有序列表。请参考下面的输入和输出示例。我顺便使用XSLT 2.0。

**Input:**
<xml>
    <numberedList>1. Number List 1</numberedList>
    <unnumberedList>Child List 1</unnumberedList>
    <unnumberedList>Child List 2</unnumberedList>
    <unnumberedList>Child List 3</unnumberedList>
    <numberedList>2. Number List 2</numberedList>
    <unnumberedList>Child List 1</unnumberedList>
    <numberedList>3. Number List 3</numberedList>
</xml>

**Output:**
<html>
<ol>
    <li>1. Number List 1</li>
    <li>
        <ul>
            <li>Child List 1</li>
            <li>Child List 2</li>
            <li>Child List 3</li>
        </ul>
    </li>
    <li>2. Number List 2</li>
    <li>
        <ul>
            <li>Child List 1</li>
        </ul>
    </li>
    <li>3. Number List 3</li>
</ol>
</html>

非常感谢任何帮助。谢谢!

3 个答案:

答案 0 :(得分:3)

尝试改进Dimitre的XSLT 2.0解决方案:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/*">
  <html>
   <ol>
     <xsl:for-each-group select="*" group-adjacent="name()">
       <xsl:choose>
         <xsl:when test="self::numberedList">
           <xsl:apply-templates select="current-group()"/>
         </xsl:when>
         <xsl:otherwise>
           <li><ul><xsl:apply-templates select="current-group()"/></ul></li>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:for-each-group>
   </ol>
  </html>
 </xsl:template>

 <xsl:template match="numberedList|unnumberedList">
  <li><xsl:apply-templates/></li>
 </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:2)

<强>予。稍微短一点的XSLT 1.0解决方案:

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

 <xsl:key name="kUlist" match="unnumberedList"
   use="generate-id(preceding-sibling::*
                        [not(self::unnumberedList)][1]
                   )"/>

 <xsl:template match="/*">
  <html>
   <xsl:apply-templates select="numberedList[1]" mode="first"/>
  </html>
 </xsl:template>

 <xsl:template match="numberedList" mode="first">
   <ol>
     <xsl:apply-templates select=". | following-sibling::*"/>
   </ol>
 </xsl:template>

 <xsl:template match="*">
  <li><xsl:apply-templates /></li>
 </xsl:template>

 <xsl:template match=
 "unnumberedList
      [not(preceding-sibling::*[1][self::unnumberedList])]">
   <li>
     <ul>
       <xsl:apply-templates mode="inUList" select=
           "key('kUlist', generate-id(preceding-sibling::*[1]))"/>
     </ul>
   </li>
 </xsl:template>

 <xsl:template match="*" mode="inUList">
   <li><xsl:value-of select="."/></li>
 </xsl:template>
 <xsl:template match="unnumberedList"/>
</xsl:stylesheet>

在提供的XML文档上应用此转换时:

<xml>
    <numberedList>1. Number List 1</numberedList>
    <unnumberedList>Child List 1</unnumberedList>
    <unnumberedList>Child List 2</unnumberedList>
    <unnumberedList>Child List 3</unnumberedList>
    <numberedList>2. Number List 2</numberedList>
    <unnumberedList>Child List 1</unnumberedList>
    <numberedList>3. Number List 3</numberedList>
</xml>

产生了想要的正确结果:

<html>
   <ol>
      <li>1. Number List 1</li>
      <li>
         <ul>
            <li>Child List 1</li>
            <li>Child List 2</li>
            <li>Child List 3</li>
         </ul>
      </li>
      <li>2. Number List 2</li>
      <li>
         <ul>
            <li>Child List 1</li>
         </ul>
      </li>
      <li>3. Number List 3</li>
   </ol>
</html>

<强> II。 XSLT 2.0解决方案 - 比我短30%

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/*">
  <html>
   <ol>
     <xsl:for-each-group select="*" group-adjacent="name()">
       <xsl:apply-templates select="current-group()"/>
     </xsl:for-each-group>
   </ol>
  </html>
 </xsl:template>

 <xsl:template match="*" mode="#default inUList">
  <li><xsl:apply-templates/></li>
 </xsl:template>

 <xsl:template match=
  "unnumberedList[preceding-sibling::*[1][not(self::unnumberedList)]]">
  <li>
   <ul>
    <xsl:apply-templates mode="inUList" select="current-group()"/>
   </ul>
  </li>
 </xsl:template>
 <xsl:template match="unnumberedList"/>
</xsl:stylesheet>

当在同一个XML文档(上面)上应用此XSLT 2.0转换时,会生成相同的正确结果

<html>
   <ol>
      <li>1. Number List 1</li>
      <li>
         <ul>
            <li>Child List 1</li>
            <li>Child List 2</li>
            <li>Child List 3</li>
         </ul>
      </li>
      <li>2. Number List 2</li>
      <li>
         <ul>
            <li>Child List 1</li>
         </ul>
      </li>
      <li>3. Number List 3</li>
   </ol>
</html>

答案 2 :(得分:0)

毫无疑问,这可以更轻松地完成,但请尝试以下方法 说明:它不言自明:-)
请注意,这也适用于XSLT 1.0。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="xml">
        <html>
            <ol>
                <xsl:apply-templates select="numberedList[1]"/>
            </ol>
        </html>
    </xsl:template>
    <xsl:template match="numberedList">
        <li>
            <xsl:value-of select="."/>
        </li>
        <xsl:apply-templates select="following-sibling::*[1]"/>
    </xsl:template>
    <xsl:template match="unnumberedList [local-name(preceding-sibling::*[1]) = 'numberedList']">
        <li>
            <ul>
                <li>
                    <xsl:value-of select="."/>
                </li>
                <xsl:apply-templates select="following-sibling::*[1] [local-name() = 'unnumberedList']"/>
            </ul>
        </li>
        <xsl:apply-templates select="following-sibling::numberedList[1]"/>
    </xsl:template>
    <xsl:template match="unnumberedList [local-name(preceding-sibling::*[1]) = 'unnumberedList']">
        <li>
            <xsl:value-of select="."/>
        </li>
        <xsl:apply-templates select="following-sibling::*[1] [local-name() = 'unnumberedList']"/>
    </xsl:template>
</xsl:stylesheet>

这给出了以下结果:

<?xml version="1.0" encoding="UTF-8"?>
<html>
    <ol>
        <li>1. Number List 1</li>
        <li>
            <ul>
                <li>Child List 1</li>
                <li>Child List 2</li>
                <li>Child List 3</li>
            </ul>
        </li>
        <li>2. Number List 2</li>
        <li>
            <ul>
                <li>Child List 1</li>
            </ul>
        </li>
        <li>3. Number List 3</li>
    </ol>
</html>