我有一个表示逻辑推导的XML结构,它看起来像这样:
<derivation>
<step name="foo">
<derive>[...]</derive>
<by>[...]</by>
</step>
<step name="bar">
<derive>[...]</derive>
<by>
<from name="foo"/>, conjunction elimination
</by>
</step>
<step name="baz">
<derive>[...]</derive>
<by>
<from name="bar"/>, existential quantification
</by>
</step>
[...]
</derivation>
派生中的每个<step>
都有一个数字 - 例如,name="foo"
的数字为1
,而name="bar"
的数字为2
},name="baz"
的数字为3
,依此类推。在<step>
内,我可以找到<xsl:number/>
的数字。好到目前为止。
现在,发生了元素<from name="bar"/>
,我希望将其替换为<step>
元素name="bar"
的数字。这里有三个子问题需要解决:
<from>
的{{1}}元素的最新祖先。<derivation>
元素与<step>
的孩子。在上面的例子中,这将找到name="bar"
的第二个孩子。<derivation>
。有人可以将这些子问题的解决方案联系起来以满足我的要求吗?
答案 0 :(得分:2)
此转化:
<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="from[@name]">
<xsl:variable name="vReferred" select=
"ancestor::derivation[1]/step[@name = current()/@name]"/>
<xsl:for-each select="$vReferred">
<xsl:number count="step" level="any"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<derivation>
<step name="foo">
<derive>[...]</derive>
<by>[...]</by>
</step>
<step name="bar">
<derive>[...]</derive>
<by>
<from name="foo"/>, conjunction elimination
</by>
</step>
<step name="baz">
<derive>[...]</derive>
<by>
<from name="bar"/>, existential quantification
</by>
</step> [...]
</derivation>
生成想要的正确结果:
<derivation>
<step name="foo">
<derive>[...]</derive>
<by>[...]</by>
</step>
<step name="bar">
<derive>[...]</derive>
<by>1, conjunction elimination
</by>
</step>
<step name="baz">
<derive>[...]</derive>
<by>2, existential quantification
</by>
</step> [...]
</derivation>
答案 1 :(得分:1)
XPath轴的乐趣......
count(ancestor::derivation/step[@name=$name]/preceding-sibling::step)+1
这会抓取最近的祖先,它是一个派生,用正确的名称获取它的子步骤,然后获取所有名为step的兄弟姐妹。它计算它们并加1(因为第2步将有1个前面的兄弟)。
答案 2 :(得分: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:key name="kStepByName" match="derivation/step"
use="@name"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="from[@name]">
<xsl:variable name="vReferred" select=
"key('kStepByName',@name)"/>
<xsl:for-each select="$vReferred">
<xsl:number count="step" level="any"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
答案 3 :(得分:0)
虽然已发布的两个解决方案都可以,但仅供参考,我正在添加另一种可能的解决方案。
类似的东西:
<xsl:template match="from">
<xsl:variable name="ref" select="@name"/>
<xsl:apply-templates mode="number" select="ancestor::derivation/step">
<xsl:with-param name="ref" select="$ref"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template name="step" mode="number">
<xsl:param name="ref"/>
<xsl:if test="@name=$ref">
Item no. <xsl:value-of select="position()"/>
</xsl:if>
</xsl:template>
请注意,我已经有好几年没有编写XSLT了,而这个解决方案背后的想法应该是正确的,语法可能完全错误。