如何循环前面的兄弟姐妹到一个点

时间:2011-09-16 06:13:43

标签: xslt

我有这个XML:

<p>
    <span>Foo</span>
    <br/>
</p>

<p>
    <span>Foo</span>
    <br/>
    <span>Foo</span>
    <span>Foo</span>
    <br/>
</p>

<p>
    <span>Foo</span>
    <span>Foo</span>
    <br/>
    <span>Foo</span>
    <span>Foo</span>
    <span>Foo</span>
    <br/>
</p>

我希望能够首先选择<br/>标记,然后遍历它们上方的跨度。这样做的原因是摆脱<br/>标签并替换为<p></p>标签,如下所示:

<p>
    <span>Foo</span>
</p>

<p>
    <span>Foo</span>
</p>

<p>
    <span>Foo</span>
    <span>Foo</span>
</p>

<p>
    <span>Foo</span>
    <span>Foo</span>
</p>

<p>
    <span>Foo</span>
    <span>Foo</span>
    <span>Foo</span>
</p>

这是我提出的那种xslt:

<xsl:template match="br">
    <p>
    <xsl:for-each select="preceding-sibling::span">
         <span>
         <xsl:value-of select="." />
         </span>
    </xsl:for-each>
    </p>
</xsl:template>

我知道这是错误的,因为它会拾取P标签内的所有跨距,而不仅仅是前一个br标签之前的跨度。任何建议真的很感激 非常感谢提前

1 个答案:

答案 0 :(得分:3)

实现此目的的一种方法是使用来匹配给定 br 标记之前的所有 span

<xsl:key name="para" match="span" use="generate-id(following-sibling::br[1])" />

即按紧随其后的第一个 br 对所有 span 标记进行分组。

然后,您可以匹配 br 元素,并使用此键获取其前面的所有关联 span 标记

<xsl:template match="br">
   <p>
      <xsl:apply-templates select="key('para', generate-id())" />
   </p>

这是完整的XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="html" indent="yes"/>

   <xsl:key name="para" match="span" use="generate-id(following-sibling::br[1])" />

   <xsl:template match="/">
      <body>
         <xsl:apply-templates select="body/p" />
      </body>
   </xsl:template>

   <xsl:template match="p">
      <xsl:apply-templates select="br" />
      <xsl:if test="span[not(following-sibling::br)]">
         <p>
            <xsl:apply-templates select="span[not(following-sibling::br)]" />
         </p>
      </xsl:if>
   </xsl:template>

   <xsl:template match="br">
      <p>
         <xsl:apply-templates select="key('para', generate-id())" />
      </p>
   </xsl:template>

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

</xsl:stylesheet>

当应用于以下输入XML时(我已将您的样本包含在 body 标记中以使其成为有效的XML

<body>
   <p>
      <span>Foo 1</span>
      <br/>
   </p>
   <p>
      <span>Foo 2</span>
      <br/>
      <span>Foo 3</span>
      <span>Foo 4</span>
      <br/>
   </p>
   <p>
      <span>Foo 5</span>
      <span>Foo 6</span>
      <br/>
      <span>Foo 7</span>
      <span>Foo 8</span>
      <span>Foo 9</span>
      <br/>
      <span>Foo 10</span>
   </p>
</body>

以下是输出:

<body>
   <p>
      <span>Foo 1</span>
   </p>
   <p>
      <span>Foo 2</span>
   </p>
   <p>
      <span>Foo 3</span>
      <span>Foo 4</span>
   </p>
   <p>
      <span>Foo 5</span>
      <span>Foo 6</span>
   </p>
   <p>
      <span>Foo 7</span>
      <span>Foo 8</span>
      <span>Foo 9</span>
   </p>
   <p>
      <span>Foo 10</span>
   </p>
</body>

请注意,作为示例,我添加了一个案例来处理段落中没有 br 标记的 span 标记。