Xml XSLT——解释文本节点';s值作为XPath查询(并在转换中使用)
我一直在试图找到一个体面的解决办法,但我甚至找不到一个不体面的办法 我有一个XML文件,看起来有点像这样:Xml XSLT——解释文本节点';s值作为XPath查询(并在转换中使用),xml,xslt,xpath,Xml,Xslt,Xpath,我一直在试图找到一个体面的解决办法,但我甚至找不到一个不体面的办法 我有一个XML文件,看起来有点像这样: <Root> <Something> <SomethingElse>Value of SomethingElse</SomethingElse> </Something> ... <Map> <Node> <Path&
<Root>
<Something>
<SomethingElse>Value of SomethingElse</SomethingElse>
</Something>
...
<Map>
<Node>
<Path>/Root/Something/SomethingElse</Path>
</Node>
<Map>
...
</Root>
我首先想到的是:
<xsl:template match="Path">
<text><xsl:value-of select="{text()}"/></text>
</xsl:template>
但这当然不起作用,因为select
不是值属性
我不知道该怎么办。谷歌搜索只返回关于如何使用XPath获取文本值的结果,而不是相反
我还想对返回的
元素应用进一步的转换,但一旦我弄明白如何做,这应该是小菜一碟
非常感谢您能走到这一步,Slampisko对于纯XSLT1.0甚至2.0,您需要使用两个样式表,第一个样式表接受输入并使用您想要使用的XPath表达式创建第二个样式表作为结果,然后针对原始输入运行第二个样式表
或者,您需要检查XSLT处理器是否支持扩展函数将字符串作为路径表达式进行求值,就像Saxon使用altova:evaluate函数或AltovaXML使用altova:evaluate函数一样。而完整的动态XPath求值不是XSLT 1.0/XPath 1.0或XSLT 2.0/XPath 2.0的一部分,我们可以生成一个XSLT 1.0实现,它的工作方式相当有限:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="text()"/>
<xsl:template match="Path" name="eval">
<xsl:param name="pPath" select="."/>
<xsl:param name="pContext" select="/"/>
<xsl:choose>
<!-- If there is something to evaluate -->
<xsl:when test="string-length($pPath) >0">
<xsl:variable name="vPath" select=
"substring($pPath,2)"/>
<xsl:variable name="vNameTest">
<xsl:choose>
<xsl:when test="not(contains($vPath, '/'))">
<xsl:value-of select="$vPath"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select=
"substring-before($vPath, '/')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:call-template name="eval">
<xsl:with-param name="pPath" select=
"substring-after($pPath, $vNameTest)"/>
<xsl:with-param name="pContext" select=
"$pContext/*[name()=$vNameTest]"/>
</xsl:call-template>
</xsl:when>
<!-- Otherwise we have evaluated completely the path -->
<xsl:otherwise>
<xsl:copy-of select="$pContext"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
<Root>
<Something>
<SomethingElse>Value of SomethingElse</SomethingElse>
</Something>
...
<Map>
<Node>
<Path>/Root/Something/SomethingElse</Path>
</Node>
</Map>
...
</Root>
<SomethingElse>Value of SomethingElse</SomethingElse>
当此转换应用于提供的XML文档时:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="text()"/>
<xsl:template match="Path" name="eval">
<xsl:param name="pPath" select="."/>
<xsl:param name="pContext" select="/"/>
<xsl:choose>
<!-- If there is something to evaluate -->
<xsl:when test="string-length($pPath) >0">
<xsl:variable name="vPath" select=
"substring($pPath,2)"/>
<xsl:variable name="vNameTest">
<xsl:choose>
<xsl:when test="not(contains($vPath, '/'))">
<xsl:value-of select="$vPath"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select=
"substring-before($vPath, '/')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:call-template name="eval">
<xsl:with-param name="pPath" select=
"substring-after($pPath, $vNameTest)"/>
<xsl:with-param name="pContext" select=
"$pContext/*[name()=$vNameTest]"/>
</xsl:call-template>
</xsl:when>
<!-- Otherwise we have evaluated completely the path -->
<xsl:otherwise>
<xsl:copy-of select="$pContext"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
<Root>
<Something>
<SomethingElse>Value of SomethingElse</SomethingElse>
</Something>
...
<Map>
<Node>
<Path>/Root/Something/SomethingElse</Path>
</Node>
</Map>
...
</Root>
<SomethingElse>Value of SomethingElse</SomethingElse>
某物的价值
...
/根/某物/某物
...
生成所需的正确结果:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="text()"/>
<xsl:template match="Path" name="eval">
<xsl:param name="pPath" select="."/>
<xsl:param name="pContext" select="/"/>
<xsl:choose>
<!-- If there is something to evaluate -->
<xsl:when test="string-length($pPath) >0">
<xsl:variable name="vPath" select=
"substring($pPath,2)"/>
<xsl:variable name="vNameTest">
<xsl:choose>
<xsl:when test="not(contains($vPath, '/'))">
<xsl:value-of select="$vPath"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select=
"substring-before($vPath, '/')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:call-template name="eval">
<xsl:with-param name="pPath" select=
"substring-after($pPath, $vNameTest)"/>
<xsl:with-param name="pContext" select=
"$pContext/*[name()=$vNameTest]"/>
</xsl:call-template>
</xsl:when>
<!-- Otherwise we have evaluated completely the path -->
<xsl:otherwise>
<xsl:copy-of select="$pContext"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
<Root>
<Something>
<SomethingElse>Value of SomethingElse</SomethingElse>
</Something>
...
<Map>
<Node>
<Path>/Root/Something/SomethingElse</Path>
</Node>
</Map>
...
</Root>
<SomethingElse>Value of SomethingElse</SomethingElse>
SomethingElse的值
我们假设以下限制条件:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="text()"/>
<xsl:template match="Path" name="eval">
<xsl:param name="pPath" select="."/>
<xsl:param name="pContext" select="/"/>
<xsl:choose>
<!-- If there is something to evaluate -->
<xsl:when test="string-length($pPath) >0">
<xsl:variable name="vPath" select=
"substring($pPath,2)"/>
<xsl:variable name="vNameTest">
<xsl:choose>
<xsl:when test="not(contains($vPath, '/'))">
<xsl:value-of select="$vPath"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select=
"substring-before($vPath, '/')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:call-template name="eval">
<xsl:with-param name="pPath" select=
"substring-after($pPath, $vNameTest)"/>
<xsl:with-param name="pContext" select=
"$pContext/*[name()=$vNameTest]"/>
</xsl:call-template>
</xsl:when>
<!-- Otherwise we have evaluated completely the path -->
<xsl:otherwise>
<xsl:copy-of select="$pContext"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
<Root>
<Something>
<SomethingElse>Value of SomethingElse</SomethingElse>
</Something>
...
<Map>
<Node>
<Path>/Root/Something/SomethingElse</Path>
</Node>
</Map>
...
</Root>
<SomethingElse>Value of SomethingElse</SomethingElse>
好问题,+1。请参阅我的答案,了解一个完整的XSLT1.0解决方案,如果接受了某些限制,该解决方案是可能的和有用的。这就是我所想的,但扩展到处理谓词是非常困难的,不是吗?@empo:是的,编写一个完整的XPath引擎即使在C#中也不容易。在XSLT1.0中,这将是非常困难的。我的XPath2.0解析器是用XSLT2.0编写的——很有可能做到,但仍然很有挑战性。投票支持这项努力。我可能会处理这种方法,但我的XPath(文本节点中的XPath)不是一系列名称测试,而是相当复杂的查询(嗯,不太复杂……不过我会测试属性值)。我举的这个简单的例子纯粹是为了让我的问题简单易懂。@Slampisko:属性测试可以很容易地添加到这个解决方案中。请更新您的问题,我很乐意回答。:)谢谢,这似乎是我一直在寻找的答案。