简体   繁体   English

如何合并(覆盖)两个xml文档?

[英]How to merge (with overwrite) two xml documents?

Suppose I have an A document like this: 假设我有一个这样的A文档:

<document>
    <element>
        <value>1</value>
        <wom>bat</wom>
    </element>
    <bar>
        <baz />
        <baz />
        <baz />
    </bar>
</document>

and a B document like this: 和这样的B文档:

<document>
    <element>
        <value>2</value>
    </element>
    <bar>

    </bar>
</document>

With the result which looks like this: 结果如下:

<document>
    <element>
        <value>2</value>
        <wom>bat</wom>
    </element>
    <bar>

    </bar>
</document>

So what I'd like to achieve is to overwrite values in a tag (like in element ) in document A with values provided from document B but leave the sibling values untouched. 因此,我想要实现的是使用文档B中提供的值覆盖文档A中标签中的值(如element中的值),而兄弟值保持不变。 If the tag in B however is empty (leaf) I want its counterpart in A to be emptied as well. 如果B中的标签是空的(叶子),我也希望将A中的标签也清空。 I've checked this question but it is merging not overwriting. 我检查了这个问题,但它不是合并而已。 How can I solve this problem? 我怎么解决这个问题?

Clarification: A and B documents have the same structure but B has less elements. 说明性: AB文档具有相同的结构,但是B的元素较少。 I have to empty every element in A which is empty in B and I have to overwrite every inner element in an element if it is not empty (see my example). 我必须清空A中的每个元素,而B中为空,并且如果它不为空,则必须覆盖元素中的每个内部元素(请参见我的示例)。

One approach could be to navigate over DocumentA, but passing in a parameter set to the equivalent node in Document B. 一种方法是在DocumentA上导航,但将参数集传递给Document B中的等效节点。

To start with, match the document node of A, and start the matching off with the document node from B 首先,匹配A的文档节点,然后从B的文档节点开始匹配

   <xsl:template match="/">
      <xsl:apply-templates>
         <xsl:with-param name="parentB" select="document('DocB.xml')"/>
      </xsl:apply-templates>
   </xsl:template>

Then, you would have a template matching any element (in A) with the current (parent) node in B as the parameter 然后,您将拥有一个模板,该模板将A中的任何元素与B中的当前(父)节点作为参数匹配

   <xsl:template match="*">
      <xsl:param name="parentB"/>

To find the equivalent 'child' node in B, you would first find the current position of the A node (should there be more than one child of the same name), and then check if such a child exists under the parent B node 要在B中找到等效的“子”节点,您首先要找到A节点的当前位置(如果有多个同名子节点),然后检查在父B节点下是否存在这样的子节点

<xsl:variable name="posA">
   <xsl:number  />
</xsl:variable>
<xsl:variable name="nodeB" select="$parentB/*[local-name() = local-name(current())][number($posA)]"/>

Then, it is just a case of determining whether to copy the A or B node. 然后,仅是确定是否复制A或B节点的情况。 To copy the B node, the B node would have to exist, and not have any child elements (it might have child text nodes though, which would be copied 要复制B节点,B节点必须存在,并且不具有任何子元素(尽管它可能具有子文本节点,但将被复制)

<xsl:when test="$nodeB and not($nodeB/*)">
   <xsl:copy-of select="$nodeB/node()"/>
</xsl:when>

Otherwise, continue processing the A node (passing in the current B node as a parameter). 否则,继续处理A节点(将当前B节点作为参数传递)。

Try this XSLT 试试这个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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM