使用此源文档:问题使用祖先轴在XPath谓词
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Element1 id="UniqueId1">
<SubElement1/>
<SubElement2>
<LeafElement1/>
<LeafElement1/>
</SubElement2>
</Element1>
<Element2 id="UniqueId2" AttributeToCheck="true">
<SubElement1>
<LeafElement1/>
<LeafElement1/>
</SubElement1>
</Element2>
</Root>
欲属性富=“栏中的”添加到该两个元件:
- 具有与同级元素同名
- 有任何祖先属性AttributeToCheck
这应该是RESU lt:
<?xml version="1.0"?>
<Root>
<Element1 id="UniqueId1">
<SubElement1/>
<SubElement2>
<LeafElement1/>
<LeafElement1/>
</SubElement2>
</Element1>
<Element2 id="UniqueId2" AttributeToCheck="true">
<SubElement1>
<LeafElement1 foo="bar"/>
<LeafElement1 foo="bar"/>
</SubElement1>
</Element2>
</Root>
这是我的表单到目前为止。它增加了匹配条件1的属性的元素,但无法说清条件2
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" indent="yes"/>
<xsl:template match="* | @*">
<xsl:copy>
<xsl:apply-templates select="* | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[count(../*[name(.) = name(current())]) > 1]">
<xsl:copy>
<xsl:attribute name="foo">bar</xsl:attribute>
<xsl:apply-templates select="* | @*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
不正确的输出:
<?xml version="1.0"?>
<Root>
<Element1 id="UniqueId1">
<SubElement1/>
<SubElement2>
<LeafElement1 foo="bar"/> (incorrect)
<LeafElement1 foo="bar"/> (incorrect)
</SubElement2>
</Element1>
<Element2 id="UniqueId2" AttributeToCheck="true">
<SubElement1>
<LeafElement1 foo="bar"/> (correct)
<LeafElement1 foo="bar"/> (correct)
</SubElement1>
</Element2>
</Root>
由于第二模板已经正确地匹配具有相同名称的兄弟姐妹元素,应该很容易使用祖先XPath轴来排除没有AttributeToCheck祖先的元素。我在第二个模板中添加了另一个谓词。
<xsl:template match="*[ancestor::*[@AttributeToCheck]][count(../*[name(.) = name(current())]) > 1]">
当我应用此样式表时,输出文档与输入文档相同,表明第二个模板与任何元素都不匹配。我也尝试改变新的谓词来使用节点数。
<xsl:template match="*[count(ancestor::*[@AttributeToCheck]) > 0][count(../*[name(.) = name(current())]) > 1]">
这也行不通,输出文件与输入文件相同。这是令人惊讶的,因为当我使用这个祖先表达式来输出具有AttributeToCheck的节点名称时,它就可以工作。我做了这些改动sylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" indent="yes"/>
<xsl:template match="* | @*">
<xsl:copy>
<xsl:apply-templates select="* | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[count(../*[name(.) = name(current())]) > 1]">
<xsl:copy>
<xsl:attribute name="foo">bar</xsl:attribute>
<xsl:attribute name="AncestorCount">
<xsl:value-of select="count(ancestor::*[@AttributeToCheck])"/>
</xsl:attribute>
<xsl:attribute name="AncestorName">
<xsl:value-of select="name(ancestor::*[@AttributeToCheck])"/>
</xsl:attribute>
<xsl:apply-templates select="* | @*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
产生这样的输出:
<?xml version="1.0"?>
<Root>
<Element1 id="UniqueId1">
<SubElement1/>
<SubElement2>
<LeafElement1 foo="bar" AncestorCount="0" AncestorName=""/>
<LeafElement1 foo="bar" AncestorCount="0" AncestorName=""/>
</SubElement2>
</Element1>
<Element2 id="UniqueId2" AttributeToCheck="true">
<SubElement1>
<LeafElement1 foo="bar" AncestorCount="1" AncestorName="Element2"/>
<LeafElement1 foo="bar" AncestorCount="1" AncestorName="Element2"/>
</SubElement1>
</Element2>
</Root>
我的问题是,为什么XPath的谓词*[ancestor::*[@AttributeToCheck]][count(../*[name(.) = name(current())]) > 1]
不正确匹配匹配两个条件1和2的元素?我应该使用什么XPath表达式?
您使用的是哪种XSL库? .NET XSL库无法在模式内处理'current()',并且(一旦我得到了补偿),* [ancestor :: * [@ AttributeToCheck]] [count(../* [name(。)= name(current())])> 1]'表达式按预期工作。我认为你的XSL库已经搞乱了。 – Welbog 2009-11-30 15:29:08
它也适用于W3Cchool的try it编辑器:http://www.w3schools.com/Xsl/tryxslt.asp?xmlfile=cdcatalog&xsltfile=cdcatalog – Welbog 2009-11-30 15:39:10
我使用的是XmlStarlet 1.0.1,我认为它是当前的版本。 XmlStarlet使用libxml2-2.7.6和libxslt-1.1.26。 – Chris 2009-11-30 16:25:46