这是我的xml:
<rootNode>
<sample>
<DO type="TD" name="ABC" ref="1">
<text>text</text>
</DO>
<DO type="CI" name="DEF" ref="2">
<text></text>
</DO>
<DO type="PL" name="GHI" ref="3">
<text>text</text>
</DO>
<DO type="AB" name="JKL" ref="4">
<text>text</text>
</DO>
</sample>
<Docs>
<Document>
<type>TD</type>
<name>ABC</name>
<ref>1</ref>
<text>sample text</text>
</Document>
<Document>
<type>CI</type>
<name>DEF</name>
<ref>2</ref>
<text>sample text</text>
</Document>
<Document>
<type>PL</type>
<name>GHI</name>
<ref>3</ref>
<text>sample text</text>
</Document>
<Document>
<type>AB</type>
<name>JKL</name>
<ref>4</ref>
<text>sample text</text>
</Document>
<Document>
<type>CD</type>
<name>JKL</name>
<ref>5</ref>
<text>sample text</text>
</Document>
</Docs>
</rootNode>
如果任何样本/ DO的类型,名称和引用与任何文档/文档类型,名称和引用匹配。使用文档/文本更新样本/ DO /文本。否则(如果任何sample / Do类型,name,ref与Docs / Document type,name,ref不匹配),则应附加Docs / Document中的整个Document。
注意:样品/ DO的顺序不应改变。我的意思是如果任何文件有任何相同的匹配应该更新。否则应附加新的。
答案 0 :(得分:1)
如果您使用XSLT复制和转换文档,则可以使用两个 xsl:key **来查找** Document 元素和 SO 元素。在这种情况下,您需要一个复合键
<xsl:key name="docs" match="Document" use="concat(type, '|', name, '|', ref)"/>
<xsl:key name="samples" match="DO" use="concat(@type, '|', @name, '|', @ref)"/>
您可以首先匹配具有匹配的文档元素的 SO 元素
<xsl:template match="DO[key('docs', concat(@type, '|', @name, '|', @ref))]">
(如果所有 SO 元素都保证具有匹配的** Document元素,则可以简化为<xsl:template match="DO" >
)
在此模板中,您只需向此模板添加代码即可复制密钥中文档元素中的文本元素。
要匹配文档元素而没有相应的 SO 元素,您可以这样做:
<xsl:apply-templates
select="/rootNode/Docs/Document[not(key('samples', concat(type, '|', name, '|', ref)))]"
mode="Document"/>
对于匹配模板,您可以将其转换为 SO 元素。
这是完整的XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="docs" match="Document" use="concat(type, '|', name, '|', ref)"/>
<xsl:key name="samples" match="DO" use="concat(@type, '|', @name, '|', @ref)"/>
<xsl:template match="DO[key('docs', concat(@type, '|', @name, '|', @ref))]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:copy-of select="key('docs', concat(@type, '|', @name, '|', @ref))/text"/>
</xsl:copy>
</xsl:template>
<xsl:template match="sample">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<xsl:apply-templates select="/rootNode/Docs/Document[not(key('samples', concat(type, '|', name, '|', ref)))]" mode="Document"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Document" mode="Document">
<DO type="{type}" name="{name}" ref="{ref}">
<xsl:copy-of select="text" />
</DO>
</xsl:template>
<xsl:template match="Docs" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
以下是输出
<rootNode>
<sample>
<DO type="TD" name="ABC" ref="1">
<text>sample text</text>
</DO>
<DO type="CI" name="DEF" ref="2">
<text>sample text</text>
</DO>
<DO type="PL" name="GHI" ref="3">
<text>sample text</text>
</DO>
<DO type="AB" name="JKL" ref="4">
<text>sample text</text>
</DO>
<DO type="CD" name="JKL" ref="5">
<text>sample text</text>
</DO>
</sample>
</rootNode>
请注意我从输出中排除了文档节点,但如果要保留它们,只需从XSLT中删除相关行。
答案 1 :(得分:0)
据我所知,你只能通过使用纯xpath来更新文档,xpath的思想主要用于根据某些比较从文档中选择特定节点。实现这一目标的唯一好方法是你需要使用另一种语言,你可以使用xpath和update元素,就像php Simplexml。阅读不同的来源很多人推荐不同的建议,但它主要解决与xquery这里有几个链接。