如何使用XSLT从平面xml文件创建html列表

如何使用XSLT从平面xml文件创建html列表,xml,xslt,xpath,xslt-2.0,xslt-grouping,Xml,Xslt,Xpath,Xslt 2.0,Xslt Grouping,我正在寻找一种干净的方法来使用XSLT完成以下工作 转换此源: <para>blah blah</para> <list>num1</list> <list>num2</list> <list>num3</list> <para>blah blah</para> <list>num1</list> <list>num2</list>

我正在寻找一种干净的方法来使用XSLT完成以下工作

转换此源:

<para>blah blah</para>
<list>num1</list>
<list>num2</list>
<list>num3</list>
<para>blah blah</para>
<list>num1</list>
<list>num2</list>
<para>blah blah blah blah blah</para>
废话
num1
num2
num3
废话
num1
num2
废话废话废话
对于此输出:

<p>blah blah</p>
<ol>
    <li>num1</li>
    <li>num2</li>
    <li>num3</li>
</ol>
<p>blah blah</p>
<ol>
    <li>num1</li>
    <li>num2</li>
</ol>
<p>blah blah blah blah blah</p>
废话废话

  • num1
  • num2
  • num3
  • 废话

  • num1
  • num2
  • 废话废话废话

    请记住,我不知道会有多少个

    到目前为止,我有:

    <xsl:template match="para">
        <p><xsl:value-of select="." /></p>
    </xsl:template>
    
    <xsl:template match="list">
        <ol><li><xsl:value-of select="." /></li></ol>
    </xsl:template>
    
    
    

  • 但我的输出如下所示:

    <p>blah blah</p>    
    <ol><li>num1</li></ol>
    <ol><li>num2</li></ol>
    <ol><li>num3</li></ol>
    <p>blah blah</p>
    <ol><li>num1</li></ol>
    <ol><li>num2</li></ol>
    <p>blah blah blah blah blah</p>
    
    废话废话
    
  • num1
  • num2
  • num3
  • 废话

  • num1
  • num2
  • 废话废话废话

    我知道为什么我会得到重复的
    元素,但我不知道如何阻止它。真是个脑筋急转弯


    任何帮助都将不胜感激。

    这一转变

    <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="kFollowing" match="list"
      use="generate-id(preceding-sibling::para[1])"/>
    
     <xsl:template match="node()|@*" name="identity">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match="para">
      <p>
        <xsl:apply-templates/>
      </p>
       <xsl:variable name="vFol"
        select="key('kFollowing',generate-id())"/>
       <xsl:if test="$vFol">
          <ol>
           <xsl:apply-templates mode="copy"
               select="key('kFollowing',generate-id())"/>
          </ol>
      </xsl:if>
     </xsl:template>
    
     <xsl:template match="list" mode="copy">
      <li><xsl:value-of select="."/></li>
     </xsl:template>
     <xsl:template match="list"/>
    </xsl:stylesheet>
    
    <t>
        <p>blah blah</p>
        <ol>
            <li>num1</li>
            <li>num2</li>
            <li>num3</li>
        </ol>
        <p>blah blah</p>
        <ol>
            <li>num1</li>
            <li>num2</li>
        </ol>
        <p>blah blah blah blah blah</p>
    </t>
    
    <t>
        <bara>blah blah</bara>
        <ol>
            <li>num1</li>
            <li>num2</li>
            <li>num3</li>
        </ol>
        <vara>blah blah</vara>
        <ol>
            <li>num1</li>
            <li>num2</li>
        </ol>
        <dara>blah blah blah blah blah</dara>
    </t>
    
    将此转换应用于以下XML文档时(请注意,分隔元素现在具有随机名称):

    
    废话
    num1
    num2
    num3
    废话
    num1
    num2
    废话废话废话
    
    生成所需的正确结果

    <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="kFollowing" match="list"
      use="generate-id(preceding-sibling::para[1])"/>
    
     <xsl:template match="node()|@*" name="identity">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match="para">
      <p>
        <xsl:apply-templates/>
      </p>
       <xsl:variable name="vFol"
        select="key('kFollowing',generate-id())"/>
       <xsl:if test="$vFol">
          <ol>
           <xsl:apply-templates mode="copy"
               select="key('kFollowing',generate-id())"/>
          </ol>
      </xsl:if>
     </xsl:template>
    
     <xsl:template match="list" mode="copy">
      <li><xsl:value-of select="."/></li>
     </xsl:template>
     <xsl:template match="list"/>
    </xsl:stylesheet>
    
    <t>
        <p>blah blah</p>
        <ol>
            <li>num1</li>
            <li>num2</li>
            <li>num3</li>
        </ol>
        <p>blah blah</p>
        <ol>
            <li>num1</li>
            <li>num2</li>
        </ol>
        <p>blah blah blah blah blah</p>
    </t>
    
    <t>
        <bara>blah blah</bara>
        <ol>
            <li>num1</li>
            <li>num2</li>
            <li>num3</li>
        </ol>
        <vara>blah blah</vara>
        <ol>
            <li>num1</li>
            <li>num2</li>
        </ol>
        <dara>blah blah blah blah blah</dara>
    </t>
    
    
    废话
    
  • num1
  • num2
  • num3
  • 废话
  • num1
  • num2
  • 废话废话废话
    此XSLT 1.0样式表:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:template match="node()">
            <xsl:apply-templates select="node()[1]|following-sibling::node()[1]"/>
        </xsl:template>
        <xsl:template match="para">
            <p>
                <xsl:value-of select="."/>
            </p>
            <xsl:apply-templates select="following-sibling::node()[1]"/>
        </xsl:template>
        <xsl:template match="list[preceding-sibling::node()[1][not(self::list)]]">
            <ol>
                <xsl:call-template name="makeList"/>
            </ol>
            <xsl:apply-templates select="following-sibling::node()
                                                  [not(self::list)][1]"/>
        </xsl:template>
        <xsl:template match="list" name="makeList">
            <li>
                <xsl:value-of select="."/>
            </li>
            <xsl:apply-templates select="following-sibling::node()[1]
                                                  [self::list]"/>
        </xsl:template>
    </xsl:stylesheet>
    
    
    
    

  • 输出:

    <p>blah blah</p>
    <ol>
            <li>num1</li>
            <li>num2</li>
            <li>num3</li>
    </ol>
    <p>blah blah</p>
    <ol>
            <li>num1</li>
            <li>num2</li>
    </ol>
    <p>blah blah blah blah blah</p>
    
    废话废话

  • num1
  • num2
  • num3
  • 废话

  • num1
  • num2
  • 废话废话废话

    注意:细粒度遍历


    编辑:压缩代码。

    XSLT 2.0有专门用于此类操作的工具:

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:template match="xml">
            <xsl:for-each-group select="*" group-adjacent="boolean(self::list)">
                <xsl:choose>
                    <xsl:when test="current-grouping-key()">
                        <ol>
                            <xsl:apply-templates select="current-group()"/>
                        </ol>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:apply-templates select="current-group()"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:template>
        <xsl:template match="para">
            <p>
                <xsl:apply-templates/>
            </p>
        </xsl:template>
        <xsl:template match="list">
            <li>
                <xsl:apply-templates/>
            </li>
        </xsl:template>
    </xsl:stylesheet>
    
    
    
    

  • 使用此XML:

    <xml>
        <para>blah blah</para>
        <list>num1</list>
        <list>num2</list>
        <list>num3</list>
        <para>blah blah</para>
        <list>num1</list>
        <list>num2</list>
        <para>blah blah blah blah blah</para>
    </xml>
    
    
    废话
    num1
    num2
    num3
    废话
    num1
    num2
    废话废话废话
    
    您将获得所需的输出:

    <p>blah blah</p>
    <ol>
        <li>num1</li>
        <li>num2</li>
        <li>num3</li>
    </ol>
    <p>blah blah</p>
    <ol>
        <li>num1</li>
        <li>num2</li>
    </ol>
    <p>blah blah blah blah blah</p>
    
    废话废话

  • num1
  • num2
  • num3
  • 废话

  • num1
  • num2
  • 废话废话废话


    你应该在

    上阅读每个小组的许多重复内容:谢谢你的帮助,这是一种可能的方法。但这种方法不难维持吗?因为我必须在匹配的每个顶级元素上添加以下同级选择。@joe:此样式表有四个规则:默认细粒度遍历规则、
    p
    规则、
    ol
    规则和
    li
    规则。所以,这是一对一的转换。我看不出难以维护的问题。你已经要求Dimitre:如果列表前有一个元素H1呢。那么,您必须声明与
    H1
    有什么关系。现在,它被绕过了。所以,有两种解决方案:复制您不想转换的所有内容,或者为
    H1
    添加规则。我也必须加入比赛。@joe:是的,将模板应用于第一个孩子和第一个跟随的兄弟姐妹就是这样。谢谢!这看起来是一个很好的方法。但我认为使用这样的“砖块”模板规则是没有好处的。