我有两个需要合并的XML文档。每个元素都有一个定义的ID。如果一个元素在两个文档中都是唯一的 - >将被添加到结果中,如果不是 - >属性将被合并。
main.xml中
<main>
<el id="1" attr1="value1" />
<el id="2" attr2="value2" default-attr="def" />
</main>
snippet.xml
<main>
<el id="2" attr2="new value2" new-attr="some value" />
<el id="3" attr3="value3" />
</main>
为result.xml
<main>
<el id="1" attr1="value1" />
<el id="2" attr2="new value2" default-attr="def" new-attr="some value" />
<el id="3" attr3="value3" />
</main>
el [@ id = 2]中的属性被合并,并且从snippet.xml覆盖了值。
我试过这个:
merge.xlst
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:param name="snippetDoc" select="document(snippet.xml)" />
<xsl:template match="@* | node() | comment()">
<xsl:copy>
<xsl:apply-templates select="@* | node() | comment()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="el">
<xsl:copy>
<!-- how to distinguish between @ids of two documents? -->
<xsl:copy-of select="$snippetDoc/main/el/[@id = @id]/@*" />
<xsl:apply-templates select="@*" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
但它需要能够区分两个文档中的相同属性。更重要的是,这不会复制snippet.xml中的唯一元素。
感谢您的帮助!
答案 0 :(得分:1)
你正在寻找的表达是......
<xsl:copy-of select="$snippetDoc/main/el[@id=current()/@id]/@*" />
您还应该在<xsl:apply-templates select="@*" />
之后添加它,以便您可以利用新属性覆盖任何现有属性(如果它们具有相同名称)的事实。
要在代码段中添加主文档中没有匹配元素的元素,您需要在匹配main
元素的模板中执行此操作。
<xsl:template match="main">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<xsl:copy-of select="$snippetDoc/main/el[not(@id=current()/el/@id)]" />
</xsl:copy>
</xsl:template>
试试这个XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:param name="snippetDoc" select="document('snippet.xml')" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="el">
<xsl:copy>
<!-- how to distinguish between @ids of two documents? -->
<xsl:apply-templates select="@*" />
<xsl:copy-of select="$snippetDoc/main/el[@id=current()/@id]/@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="main">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<xsl:copy-of select="$snippetDoc/main/el[not(@id=current()/el/@id)]" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
请注意,node()
实际上是*|text()|comment()|processing-instruction()
的简称,因此实际上不需要node()|comment()
。