假设我有一个像这样的 A 文档:
<document>
<element>
<value>1</value>
<wom>bat</wom>
</element>
<bar>
<baz />
<baz />
<baz />
</bar>
</document>
以及 B 这样的文档:
<document>
<element>
<value>2</value>
</element>
<bar>
</bar>
</document>
结果如下:
<document>
<element>
<value>2</value>
<wom>bat</wom>
</element>
<bar>
</bar>
</document>
所以我想要实现的是使用文档 B 中提供的值覆盖文档 A 中的标记(例如element
)中的值但保持兄弟姐妹的价值不受影响。如果 B 中的标记为空(叶子),我希望其中 A 中的对应项也被清空。我已经检查了this问题,但它正在合并而不是覆盖。我该如何解决这个问题?
澄清: 和 B 文档具有相同的结构,但 B 的元素较少。我必须清空 A 中的每个元素,这些元素在 B 中为空,如果元素不为空,我必须覆盖元素中的每个内部元素(参见我的示例)。 / p>
答案 0 :(得分:4)
一种方法可能是在DocumentA上导航,但将参数集传递给文档B中的等效节点。
首先,匹配A的文档节点,然后从B
开始匹配文档节点 <xsl:template match="/">
<xsl:apply-templates>
<xsl:with-param name="parentB" select="document('DocB.xml')"/>
</xsl:apply-templates>
</xsl:template>
然后,你将有一个模板匹配任何元素(在A中)与B中的当前(父)节点作为参数
<xsl:template match="*">
<xsl:param name="parentB"/>
找到等效的孩子&#39;在B中的节点,你首先会找到A节点的当前位置(如果有多个同名的子节点),然后检查父B节点下是否存在这样的子节点
<xsl:variable name="posA">
<xsl:number />
</xsl:variable>
<xsl:variable name="nodeB" select="$parentB/*[local-name() = local-name(current())][number($posA)]"/>
然后,只是确定是否复制A或B节点的情况。要复制B节点,B节点必须存在,并且没有任何子元素(它可能有子文本节点,但可以复制
<xsl:when test="$nodeB and not($nodeB/*)">
<xsl:copy-of select="$nodeB/node()"/>
</xsl:when>
否则,继续处理A节点(将当前B节点作为参数传入)。
试试这个XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates>
<xsl:with-param name="parentB" select="document('DocB.xml')"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*">
<xsl:param name="parentB"/>
<xsl:variable name="posA">
<xsl:number />
</xsl:variable>
<xsl:variable name="nodeB" select="$parentB/*[local-name() = local-name(current())][number($posA)]"/>
<xsl:copy>
<xsl:choose>
<xsl:when test="$nodeB and not($nodeB/*)">
<xsl:copy-of select="$nodeB/node()"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="@*|node()">
<xsl:with-param name="parentB" select="$nodeB"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()[not(self::*)]">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>