0

我有这样的事情:

<root>
  <a>foo</a>
  <b>bar</b>
  <groupme>foobar</groupme>
  <groupme>baz</groupme>
  <groupme>42</groupme>
  <c>abc</c>
  <d>def</d>
  <groupme>foo</groupme>
  <x>xyz</x>
  <groupme>bar</groupme>
  <groupme>foo</groupme>
  <z>thats it</z>
</root>

现在我需要所有直接邻居的 groume 成为单个节点,例如:

<root>
  <a>foo</a>
  <b>bar</b>
  <groupme>foobar baz 42</groupme>
  <c>abc</c>
  <d>def</d>
  <groupme>foo</groupme>
  <x>xyz</x>
  <groupme>bar foo</groupme>
  <z>thats it</z>
</root>

还有包含其他节点的 groupme 节点,我只是让它们提供一个简单的示例。groupme 节点仅出现在特定级别,其他节点中没有 groupme 节点然后是 root。

对我有什么帮助吗?

4

1 回答 1

0

这种分组可以通过一种称为“兄弟递归”的方法来实现,对于您的问题,我建议使用如下样式表:

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

<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>

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

<xsl:template match="root/groupme[not(preceding-sibling::*[1][self::groupme])]">
  <xsl:copy>
    <xsl:apply-templates select="node()"/>
    <xsl:apply-templates select="following-sibling::*[1][self::groupme][1]" mode="list"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="root/groupme[preceding-sibling::*[1][self::groupme]]"/>


<xsl:template match="root/groupme[preceding-sibling::*[1][self::groupme]]" mode="list">
  <xsl:text> </xsl:text>
  <xsl:apply-templates select="node()"/>
  <xsl:apply-templates select="following-sibling::*[1][self::groupme][1]" mode="list"/>
</xsl:template>

</xsl:stylesheet>

当应用于输入时

<root>
  <a>foo</a>
  <b>bar</b>
  <groupme>foobar</groupme>
  <groupme>baz</groupme>
  <groupme>42</groupme>
  <c>abc</c>
  <d>def</d>
  <groupme>foo</groupme>
  <x>xyz</x>
  <groupme>bar</groupme>
  <groupme>foo</groupme>
  <z>thats it</z>
</root>

结果是

<root>
  <a>foo</a>
  <b>bar</b>
  <groupme>foobar baz 42</groupme>
  <c>abc</c>
  <d>def</d>
  <groupme>foo</groupme>
  <x>xyz</x>
  <groupme>bar foo</groupme>
  <z>thats it</z>
</root>

作为兄弟递归的替代方案,还可以使用基于键的方法“抓取”以下兄弟:

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

<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>

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

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

<xsl:template match="root/groupme[not(preceding-sibling::*[1][self::groupme])]">
  <xsl:copy>
    <xsl:apply-templates select="node()"/>
    <xsl:apply-templates select="key('first', generate-id())" mode="list"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="root/groupme[preceding-sibling::*[1][self::groupme]]"/>

<xsl:template match="root/groupme" mode="list">
  <xsl:text> </xsl:text>
  <xsl:apply-templates select="node()"/>
</xsl:template>

</xsl:stylesheet>
于 2013-05-13T09:06:29.603 回答