我正在尝试替换一些节点值。思路是在其他结构中查找同名节点并替换该值。
在这里,我使用 Rule/A 更改 Body/A 和使用 Rule/D 更改 Body/C/D 的值。
类似这样的事情。
<Message>
<XMLNSC>
<MaXML>
<Rule>
<A>RuleA</A>
<D>RuleD</D>
<E>RuleE</E>
</Rule>
<Body>
<A>valA</A>
<B>valB</B>
<C>
<D>valD</D>
</C>
</Body>
</MaXML>
</XMLNSC>
对此。
<Message>
<XMLNSC>
<MaXML>
<Rule>
<A>RuleA</A>
<D>RuleD</D>
<E>RuleE</E>
</Rule>
<Body>
<A>RuleA</A>
<B>valB</B>
<C>
<D>RuleD</D>
</C>
</Body>
</MaXML>
</XMLNSC>
当前我正在循环所有子节点,搜索节点名称之间的匹配,但是我应该如何保持相同的结构并仅更改值?
<?xml version="1.0" encoding="utf-8"?>
<xsl:output method="xml" indent="yes"/>
<!-- copy all -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- match Body -->
<xsl:template match="Body">
<Body>
<!-- all children from body -->
<xsl:for-each select="descendant::*">
<xsl:variable name="maNode" select="."/>
<xsl:variable name="nodeName" select="name()"/>
<!-- all rules -->
<xsl:for-each select="//Rule/*">
<xsl:variable name="varRuleName" select="name()"/>
<xsl:choose>
<!-- match rule -->
<xsl:when test="$nodeName = $varRuleName">
<element name="match"/>
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<element name="unmatch"/>
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
</Body>
</xsl:template>
最佳答案
使用身份模板的方法
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
很好,现在要使用它,您只需为要更改的元素添加模板即可,例如
<xsl:template match="Body/A">
<xsl:copy>
<xsl:value-of select="ancestor::MaXML/Rule/A"/>
</xsl:copy>
</xsl:template>
https://xsltfiddle.liberty-development.net/pPqsHTK
应该很清楚我希望如何添加第三个匹配Body/C/D
的模板,并根据需要从相应的Rule
中选择值。
如果您需要通用方法,那么在 XSLT 2 或 3 中,可以通过子树中的键和键函数调用轻松实现:
<xsl:key name="ref" match="MaXML/Rule/*" use="node-name()"/>
<xsl:template match="Body//*[key('ref', node-name(), ancestor::MaXML)]">
<xsl:copy>
<xsl:value-of select="key('ref', node-name(), ancestor::MaXML)"/>
</xsl:copy>
</xsl:template>
完整的 XSLT 3 位于 https://xsltfiddle.liberty-development.net/pPqsHTK/3那么就是
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:key name="ref" match="MaXML/Rule/*" use="node-name()"/>
<xsl:template match="Body//*[key('ref', node-name(), ancestor::MaXML)]">
<xsl:copy>
<xsl:value-of select="key('ref', node-name(), ancestor::MaXML)"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
不幸的是,XSLT 1 没有 key
函数的第三个参数,因此要使用键实现通用方法,您需要包含 generate-id(ancestor::MaXML)
在键值中:
<xsl:key name="ref" match="MaXML/Rule/*" use="concat(generate-id(ancestor::MaXML), '|', name())"/>
<xsl:template match="Body//*[key('ref', concat(generate-id(ancestor::MaXML), '|', name()))]">
<xsl:copy>
<xsl:value-of select="key('ref', concat(generate-id(ancestor::MaXML), '|', name()))"/>
</xsl:copy>
</xsl:template>
关于xml - XSL - 替换其他结构中同名的节点值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52008878/