2017-02-27 64 views
1

我有两个需要合并的XML文档。每个元素都有一个定义的ID。如果一个元素在两个文档中都是唯一的 - >将被添加到结果中,否则 - 属性将被合并。XSLT合并两个文档中元素的属性

main.xml中

<main> 
    <el id="1" attr1="value1" /> 
    <el id="2" attr2="value2" default-attr="def" /> 
</main> 

snippet.xml在EL

<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> 

属性合并[@ 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中的独特元素。

感谢您的帮助!

回答

1

你正在寻找的是这样的你也应该把这个<xsl:apply-templates select="@*" />所以以后你可以采取的事实,新属性将覆盖,如果编写的任何现有属性优势表达....

<xsl:copy-of select="$snippetDoc/main/el[@id=current()/@id]/@*" /> 

他们具有相同的名称。

要在代码片段中添加主文档中没有匹配元素的元素,您需要在匹配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()实际上是不必要的。