我想处理一些节点并再次处理这些节点的子集,特别是那些'n'祖先有一个直接子'x'的节点。
尽可能简化XML:
<root>
<s>
</s>
<s>
<n>
<w a="Hello"/>
<n>
<x/>
<w a="he said"/>
</n>
</n>
<n>
<w a="how are you"/>
</n>
<n>
</n>
<n>
<w a="she answered"/>
<n>
<n>
<x/>
<w a="friendly"/>
</n>
</n>
</n>
</s>
</root>
由于我必须两次处理一些w节点,所以我决定使用模式。我有两种模式(为了可读性,名为'fromone','fromtwo'在这里)匹配'a-attribute',并且还尝试了仅使用一种模式的各种组合,添加了没有模式的空模板,但结果保持不变。
XSLT的相关部分,也简化了,原始模板大多与条件匹配(除了具有模式的模板):
<xsl:template match="root/s">
<output>
<one>
<xsl:apply-templates select="descendant::w"/>
</one>
<x>
<xsl:apply-templates select="n"/>
</x>
</output>
</xsl:template>
<xsl:template match="n[x]">
<xsl:apply-templates select="descendant::w/@a" mode="fromtwo"/>
</xsl:template>
<xsl:template match="w">
<xsl:apply-templates select="@a" mode="fromone"/>
</xsl:template>
<xsl:template match="@a" mode="fromtwo">
<fromtwo>
<xsl:value-of select="."/>
</fromtwo>
</xsl:template>
<xsl:template match="@a" mode="fromone">
<fromone>
<xsl:value-of select="."/>
</fromone>
</xsl:template>
我希望输出看起来像这样:
<root>
<output>
<one>
<fromone>Hello</fromone>
<fromone>he said</fromone>
<fromone>how are you</fromone>
<fromone>she answered</fromone>
<fromone>friendly</fromone>
</one>
<x>
<fromtwo>he said</fromtwo>
<fromtwo>friendly</fromtwo>
</x>
</output>
</root>
但是在实际结果中,节点x包含我希望仅匹配来自另一个模板调用的元素到'fromone':
<x>
<fromone>Hello</fromone>
<fromtwo>he said</fromtwo>
<fromone>how are you</fromone>
<fromone>she answered</fromone>
<fromtwo>friendly</fromtwo>
</x>
由于这是我从我尝试的所有XSLT处理器得到的结果,我假设我的模板结构有错误。即使在阅读了有关模式问题的其他帖子之后,我也无法接近解决方案或在XSLT中找到我的错误。
我犯了什么错误?
为什么结果具有两个模板的混合输出而不是仅显示'fromtwo'的输出?
答案 0 :(得分:0)
我犯了什么错误?
当你这样做时:
<x>
<xsl:apply-templates select="n"/>
</x>
您正在将模板应用于所有 n
元素。与匹配n
的模板不匹配的n[x]
元素将由默认built in template处理:
<xsl:template match="*|/">
<xsl:apply-templates/>
</xsl:template>
即。它将递归地将模板应用于后代,直到它到达w
元素 - 您有自定义模板:
<xsl:template match="w">
<xsl:apply-templates select="@a" mode="fromone"/>
</xsl:template>
为什么你不能简单地做到:
<xsl:stylesheet version="1.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="root">
<output>
<one>
<xsl:apply-templates select=".//w"/>
</one>
<x>
<xsl:apply-templates select=".//n[x]//w" mode="fromtwo"/>
</x>
</output>
</xsl:template>
<xsl:template match="w">
<fromone>
<xsl:value-of select="@a"/>
</fromone>
</xsl:template>
<xsl:template match="w" mode="fromtwo">
<fromtwo>
<xsl:value-of select="@a"/>
</fromtwo>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
这是一个默认模板的问题,它捕获每个n
- 元素而没有x
- 子元素。如果您在<xsl:apply-templates select="n"/>
- 节点的上下文中应用s
,则s
的任何直接后继者都不会拥有x
- 子节点,这样您的模板{{ 1}}永远不会匹配。由于没有其他模板匹配,默认模板就会到位并应用每个没有模式的子节点。
所以我添加了一个模板来处理所有n[x]
- 没有n
的节点 - 子元素:
x
应用于上面的示例,它会产生以下输出:
<xsl:template match="n[not(x)]">
<xsl:apply-templates select="n"/>
</xsl:template>