如何使用xslt在其中创建新列表和标记节点

时间:2011-04-28 15:46:49

标签: list xslt

我正在使用Identity Transformation将XML转换为另一个,并且在此期间,基于我想要在新列表中标记几个节点的条件。 假设,我有一个XML:
 <点头>
     < A>将< / A>
        &LT b取代; B< / B个
        &LT c取代;< p为H. P1< / P>< / c取代;
        &LT c取代;< p为H. P2< / P>< / c取代;
        &LT c取代;< p为H. P3< / P>< / c取代;
        &LT c取代;< p为H. P4< / P>< / c取代;
< /点头>

从这个XML中,我想将'nod'的名称更新为'newnod'并为元素'c'创建一个有序列表;所以输出如下:
 < newnod>
     < A>将< / A>
        &LT b取代; B< / B个
        < orderedlist>
        <列表项>< p为H. P1< / P>< /列表项>
        <列表项>< p为H. P2< / P>< /列表项>
        <列表项>< p为H. P3< / P>< /列表项>
        <列表项>< p为H. P4< / P>< /列表项>
< / orderedlist>
< / newnod>

有人可以告诉我怎么做。

谢谢!!!

4 个答案:

答案 0 :(得分:1)

这会为您的示例生成所需的输出:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output indent="yes"/>

  <xsl:template match="/nod">
    <newnod>
      <xsl:copy-of select="*[not( self::c )]"/>
      <orderedlist>
        <xsl:apply-templates select="c">
          <xsl:sort/>
        </xsl:apply-templates>
      </orderedlist>
    </newnod>
  </xsl:template>

  <xsl:template match="nod/c">
    <listitem>
      <xsl:copy-of select="node()"/>
    </listitem>
  </xsl:template>

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

</xsl:stylesheet>

请注意,您可能需要对实际输入进行一些调整。例如,排序的细节。或abc的序列。并将所有c混为一谈?但它适用于您的样本。

答案 1 :(得分:1)

这是一个真正的“推式”解决方案:

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

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

 <xsl:template match="/nod">
  <newnod>
   <xsl:apply-templates select="node()|@*"/>
  </newnod>
 </xsl:template>

 <xsl:template match="c[1]">
  <orderedlist>
   <xsl:apply-templates mode="wrap"
    select=".|following-sibling::c"/>
  </orderedlist>
 </xsl:template>

 <xsl:template match="c" mode="wrap">
  <listitem>
   <xsl:apply-templates/>
  </listitem>
 </xsl:template>

 <xsl:template match="c"/>
</xsl:stylesheet>

将此转换应用于提供的XML文档

<nod>
 <a>A</a>
 <b>B</b>
 <c><p>p1</p></c>
 <c><p>p2</p></c>
 <c><p>p3</p></c>
 <c><p>p4</p></c>
</nod>

产生了想要的正确结果

<newnod>
  <a>A</a>
  <b>B</b>
  <orderedlist>
    <listitem>
      <p>p1</p>
    </listitem>
    <listitem>
      <p>p2</p>
    </listitem>
    <listitem>
      <p>p3</p>
    </listitem>
    <listitem>
      <p>p4</p>
    </listitem>
  </orderedlist>
</newnod>

答案 2 :(得分:0)

您可以使用以下内容:

<xsl:template match="nod">
    <newnod>
        <xsl:copy-of select="a"/>
        <xsl:copy-of select="b"/>
        <orderedlist>
            <xsl:for-each select="c">
                <listitem><p><xsl:value-of select="."/></p></listitem>
            </xsl:for-each>
        </orderedlist>
    </newnod>
</xsl:template>

答案 3 :(得分:0)

其他方法是遍历以下轴:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()[1]|@*"/>
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="nod">
        <newnod>
            <xsl:apply-templates select="node()[1]|@*"/>
        </newnod>
        <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="c">
        <orderedlist>
            <xsl:call-template name="wrap"/>
        </orderedlist>
        <xsl:apply-templates select="following-sibling::node()[1]"
                             mode="search"/>
    </xsl:template>
    <xsl:template match="c" name="wrap" mode="wrap">
        <listitem>
            <xsl:apply-templates select="node()[1]|@*"/>
        </listitem>
        <xsl:apply-templates select="following-sibling::node()[1]"
                             mode="wrap"/>
    </xsl:template>
    <xsl:template match="node()" mode="wrap"/>
    <xsl:template match="c" mode="search">
        <xsl:apply-templates select="following-sibling::node()[1]"
                             mode="search"/>
    </xsl:template>
    <xsl:template match="node()" mode="search">
        <xsl:apply-templates select="."/>
    </xsl:template>
</xsl:stylesheet>

或更短(更“推式”):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()[1]|@*"/>
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="nod">
        <newnod>
            <xsl:apply-templates select="node()[1]|@*"/>
        </newnod>
        <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="c">
        <orderedlist>
            <xsl:call-template name="wrap"/>
        </orderedlist>
        <xsl:apply-templates select="following-sibling::node()
                                        [not(self::c)][1]"/>
    </xsl:template>
    <xsl:template match="c" name="wrap" mode="wrap">
        <listitem>
            <xsl:apply-templates select="node()[1]|@*"/>
        </listitem>
        <xsl:apply-templates select="following-sibling::node()[1]
                                        /self::c"
                             mode="wrap"/>
    </xsl:template>
</xsl:stylesheet>

两个输出:

<newnod>
    <a>A</a>
    <b>B</b>
    <orderedlist>
        <listitem>
            <p>p1</p>
        </listitem>
        <listitem>
            <p>p2</p>
        </listitem>
        <listitem>
            <p>p3</p>
        </listitem>
        <listitem>
            <p>p4</p>
        </listitem>
    </orderedlist>
</newnod>

注意:即使使用XSLT 2.0,使用此模式也可以更好地表达一些复杂的序列处理。