请考虑以下xml:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<base>
<a>
<b>
<c>Text 1</c>
</b>
</a>
</base>
<base>
<a>
<b>
<c>Text 2</c>
</b>
</a>
</base>
</root>
和这个xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="1.0">
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:apply-templates select="root/base[1]" />
</xsl:template>
<xsl:template match="base//*">
<xsl:if test="text()">
<xsl:value-of select="text()" />
<!-- i need Text 2 here -->
</xsl:if>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="text()" />
</xsl:stylesheet>
原始的xml更嵌套,我不知道确切的结构。但是有一个具有相同结构的并行节点。如果我的模板位于// root / base [1] / a / b / c,我想引用// root / base [2] / a / b / c
但是我只知道我在// root / base [1]下面的某个节点,并且// root / base [2]中有相同的节点。
是否有可能实现这一目标?
答案 0 :(得分:1)
使用saxon的解决方案:评估扩展名(http://saxon.sourceforge.net/saxon7.9/extensions.html#evaluate)
如果您使用的是xslt 1.0处理器(http://exslt.org/dyn/index.html),也可以使用dyn:evaluate:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
xmlns:saxon="http://saxon.sf.net/"
version="1.0">
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:apply-templates select="root/base[1]" />
</xsl:template>
<xsl:template match="base//*">
<xsl:if test="text()">
<xsl:variable name="path">
<xsl:call-template name="constructPath">
<xsl:with-param name="node" select="."/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="rewritedPath" select="concat('/root/base[2]', substring($path, 11))"/>
<xsl:value-of select="text()" />
<xsl:value-of select="saxon:evaluate($rewritedPath)" />
</xsl:if>
<xsl:apply-templates />
</xsl:template>
<xsl:template name="constructPath">
<xsl:param name="node"/>
<xsl:choose>
<xsl:when test="$node/parent::node()/name()">
<xsl:call-template name="constructPath">
<xsl:with-param name="node" select="$node/parent::node()"/>
</xsl:call-template>
<xsl:value-of select="concat('/', $node/name())"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat('/', $node/name())"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="text()" />
</xsl:stylesheet>
这里我们使用递归模板&#34; constructPath&#34;创建字符串并在evaluate()函数中处理它。这将选择并行分支中的确切节点。希望这会有所帮助。
答案 1 :(得分:1)
此样式表不需要扩展,也不对唯一名称做任何假设;无聊的部分是通过正确的&#34;双节点&#34;每次拨打xsl:apply-templates
:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="1.0">
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:apply-templates select="root/base[1]">
<xsl:with-param name="twin" select="root/base[2]"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*">
<xsl:param name="twin"/>
<xsl:if test="text()">
<xsl:value-of select="text()" />
<xsl:value-of select="$twin/text()"/>
</xsl:if>
<xsl:for-each select="*">
<xsl:variable name="pos" select="position()"/>
<xsl:apply-templates select=".">
<xsl:with-param name="twin" select="$twin/*[$pos]"/>
</xsl:apply-templates>
</xsl:for-each>
</xsl:template>
<xsl:template match="text()" />
</xsl:stylesheet>
答案 2 :(得分:0)
尝试以下代码。仅当每个基本元素具有具有唯一元素名称的子元素时,此代码才有效。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="1.0">
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:apply-templates select="root/base[1]" />
</xsl:template>
<xsl:template match="base//*">
<xsl:if test="text()">
<xsl:variable name="name" select="name()"/>
<xsl:value-of select="text()" />
<xsl:value-of select="ancestor::base/following-sibling::base[1]//*[name() = $name]" />
</xsl:if>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="text()" />
但是你可以使用dyn:来自exslt扩展或saxon:eval