1

我目前正在研究将以下 xml 转换为有序列表的 XSL 脚本。请参考下面的输入和输出示例。顺便说一句,我正在使用 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>

任何帮助将不胜感激。谢谢!

4

3 回答 3

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>
于 2012-04-20T07:54:42.963 回答
2

I. 稍短的 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>

二、XSLT 2.0 解决方案——比 I 短 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>

当此 XSLT 2.0 转换应用于同一个 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>
于 2012-04-20T03:31:11.140 回答
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>
于 2012-04-19T23:30:48.887 回答