Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
合并具有相同结构和不同数据的XML文件_Xml_Merge - Fatal编程技术网

合并具有相同结构和不同数据的XML文件

合并具有相同结构和不同数据的XML文件,xml,merge,Xml,Merge,我正在尝试合并两个具有相同结构和一些共同数据的文件。因此,如果一个节点在两个文件中具有相同的名称,则应使用两个原始节点的子节点创建一个新节点。原始文件如下所示: file1.xml <?xml version='1.0' encoding='UTF-8'?> <BROADRIDGE> <SECURITY CUSIP='CUSIP1' DESCRIPT='CUSIP1'> <CUSTOMER ID='M1'/>

我正在尝试合并两个具有相同结构和一些共同数据的文件。因此,如果一个节点在两个文件中具有相同的名称,则应使用两个原始节点的子节点创建一个新节点。原始文件如下所示:

file1.xml
<?xml version='1.0' encoding='UTF-8'?>
<BROADRIDGE>
    <SECURITY CUSIP='CUSIP1' DESCRIPT='CUSIP1'>
        <CUSTOMER ID='M1'/>
        <CUSTOMER ID='M2'/>
        <CUSTOMER ID='M3'/>
    </SECURITY>
    <SECURITY CUSIP='CUSIP3' DESCRIPT='CUSIP3'>
        <CUSTOMER ID='M4'/>
        <CUSTOMER ID='M5'/>
        <CUSTOMER ID='M6'/>
    </SECURITY>
</BROADRIDGE>

file2.xml
<?xml version='1.0' encoding='UTF-8'?>
<BROADRIDGE>
    <SECURITY CUSIP='CUSIP1' DESCRIPT='CUSIP1'>
        <CUSTOMER ID='B1'/>
        <CUSTOMER ID='B2'/>
        <CUSTOMER ID='B3'/>
    </SECURITY>
    <SECURITY CUSIP='CUSIP2' DESCRIPT='CUSIP2'>
        <CUSTOMER ID='B4'/>
        <CUSTOMER ID='B5'/>
        <CUSTOMER ID='B6'/>
    </SECURITY>
</BROADRIDGE>
<?xml version="1.0" encoding="UTF-8"?>
<BROADRIDGE>
    <SECURITY CUSIP="CUSIP1">
        <CUSTOMER ID="M1"/>
        <CUSTOMER ID="M2"/>
        <CUSTOMER ID="M3"/>
        <CUSTOMER ID='B1'/>
        <CUSTOMER ID='B2'/>
        <CUSTOMER ID='B3'/>
    </SECURITY>
    <SECURITY CUSIP="CUSIP3">
        <CUSTOMER ID="M4"/>
        <CUSTOMER ID="M5"/>
        <CUSTOMER ID="M6"/>
    </SECURITY>
    <SECURITY CUSIP="CUSIP2">
        <CUSTOMER ID="B4"/>
        <CUSTOMER ID="B5"/>
        <CUSTOMER ID="B6"/>
    </SECURITY>
</BROADRIDGE>
<?xml version="1.0" encoding="UTF-8"?>
<BROADRIDGE>
    <SECURITY CUSIP="CUSIP1">
        <CUSTOMER ID="M1"/>
        <CUSTOMER ID="M2"/>
        <CUSTOMER ID="M3"/>
    </SECURITY>
    <SECURITY CUSIP="CUSIP3">
        <CUSTOMER ID="M4"/>
        <CUSTOMER ID="M5"/>
        <CUSTOMER ID="M6"/>
    </SECURITY>
    <SECURITY CUSIP="CUSIP2">
        <CUSTOMER ID="B4"/>
        <CUSTOMER ID="B5"/>
        <CUSTOMER ID="B6"/>
    </SECURITY>
</BROADRIDGE>
file1.xml
file2.xml
其思想是创建一个具有相同结构的新XML文件,其中包含来自这两个文件的信息,合并具有相同CUSIP属性的安全节点。在这种情况下,结果应如下所示:

file1.xml
<?xml version='1.0' encoding='UTF-8'?>
<BROADRIDGE>
    <SECURITY CUSIP='CUSIP1' DESCRIPT='CUSIP1'>
        <CUSTOMER ID='M1'/>
        <CUSTOMER ID='M2'/>
        <CUSTOMER ID='M3'/>
    </SECURITY>
    <SECURITY CUSIP='CUSIP3' DESCRIPT='CUSIP3'>
        <CUSTOMER ID='M4'/>
        <CUSTOMER ID='M5'/>
        <CUSTOMER ID='M6'/>
    </SECURITY>
</BROADRIDGE>

file2.xml
<?xml version='1.0' encoding='UTF-8'?>
<BROADRIDGE>
    <SECURITY CUSIP='CUSIP1' DESCRIPT='CUSIP1'>
        <CUSTOMER ID='B1'/>
        <CUSTOMER ID='B2'/>
        <CUSTOMER ID='B3'/>
    </SECURITY>
    <SECURITY CUSIP='CUSIP2' DESCRIPT='CUSIP2'>
        <CUSTOMER ID='B4'/>
        <CUSTOMER ID='B5'/>
        <CUSTOMER ID='B6'/>
    </SECURITY>
</BROADRIDGE>
<?xml version="1.0" encoding="UTF-8"?>
<BROADRIDGE>
    <SECURITY CUSIP="CUSIP1">
        <CUSTOMER ID="M1"/>
        <CUSTOMER ID="M2"/>
        <CUSTOMER ID="M3"/>
        <CUSTOMER ID='B1'/>
        <CUSTOMER ID='B2'/>
        <CUSTOMER ID='B3'/>
    </SECURITY>
    <SECURITY CUSIP="CUSIP3">
        <CUSTOMER ID="M4"/>
        <CUSTOMER ID="M5"/>
        <CUSTOMER ID="M6"/>
    </SECURITY>
    <SECURITY CUSIP="CUSIP2">
        <CUSTOMER ID="B4"/>
        <CUSTOMER ID="B5"/>
        <CUSTOMER ID="B6"/>
    </SECURITY>
</BROADRIDGE>
<?xml version="1.0" encoding="UTF-8"?>
<BROADRIDGE>
    <SECURITY CUSIP="CUSIP1">
        <CUSTOMER ID="M1"/>
        <CUSTOMER ID="M2"/>
        <CUSTOMER ID="M3"/>
    </SECURITY>
    <SECURITY CUSIP="CUSIP3">
        <CUSTOMER ID="M4"/>
        <CUSTOMER ID="M5"/>
        <CUSTOMER ID="M6"/>
    </SECURITY>
    <SECURITY CUSIP="CUSIP2">
        <CUSTOMER ID="B4"/>
        <CUSTOMER ID="B5"/>
        <CUSTOMER ID="B6"/>
    </SECURITY>
</BROADRIDGE>

我已经定义了用于连接它们的folling xml:

<?xml version="1.0"?>                                  
<MASTERFILE>
   <FILE>\file1.xml</FILE>
   <FILE>\file2.xml</FILE>
</MASTERFILE>

\file1.xml
\file2.xml
使用以下XSL进行合并:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/MASTERFILE">
        <BROADRIDGE>
            <xsl:variable name="securities" select="document(FILE)/BROADRIDGE/SECURITY"/>
            <xsl:for-each select="$securities">
                <xsl:if test="generate-id(.) = generate-id($securities[@CUSIP=current()/@CUSIP])">
                    <SECURITY>
                        <xsl:attribute name="CUSIP" ><xsl:value-of select="@CUSIP"/></xsl:attribute>
                        <xsl:for-each select="CUSTOMER">
                            <CUSTOMER>
                                <xsl:attribute name="ID" ><xsl:value-of select="@ID"/></xsl:attribute>
                            </CUSTOMER>
                        </xsl:for-each>
                    </SECURITY>
                </xsl:if>
            </xsl:for-each>
        </BROADRIDGE>
    </xsl:template>
</xsl:stylesheet>

但我得到了以下信息:

file1.xml
<?xml version='1.0' encoding='UTF-8'?>
<BROADRIDGE>
    <SECURITY CUSIP='CUSIP1' DESCRIPT='CUSIP1'>
        <CUSTOMER ID='M1'/>
        <CUSTOMER ID='M2'/>
        <CUSTOMER ID='M3'/>
    </SECURITY>
    <SECURITY CUSIP='CUSIP3' DESCRIPT='CUSIP3'>
        <CUSTOMER ID='M4'/>
        <CUSTOMER ID='M5'/>
        <CUSTOMER ID='M6'/>
    </SECURITY>
</BROADRIDGE>

file2.xml
<?xml version='1.0' encoding='UTF-8'?>
<BROADRIDGE>
    <SECURITY CUSIP='CUSIP1' DESCRIPT='CUSIP1'>
        <CUSTOMER ID='B1'/>
        <CUSTOMER ID='B2'/>
        <CUSTOMER ID='B3'/>
    </SECURITY>
    <SECURITY CUSIP='CUSIP2' DESCRIPT='CUSIP2'>
        <CUSTOMER ID='B4'/>
        <CUSTOMER ID='B5'/>
        <CUSTOMER ID='B6'/>
    </SECURITY>
</BROADRIDGE>
<?xml version="1.0" encoding="UTF-8"?>
<BROADRIDGE>
    <SECURITY CUSIP="CUSIP1">
        <CUSTOMER ID="M1"/>
        <CUSTOMER ID="M2"/>
        <CUSTOMER ID="M3"/>
        <CUSTOMER ID='B1'/>
        <CUSTOMER ID='B2'/>
        <CUSTOMER ID='B3'/>
    </SECURITY>
    <SECURITY CUSIP="CUSIP3">
        <CUSTOMER ID="M4"/>
        <CUSTOMER ID="M5"/>
        <CUSTOMER ID="M6"/>
    </SECURITY>
    <SECURITY CUSIP="CUSIP2">
        <CUSTOMER ID="B4"/>
        <CUSTOMER ID="B5"/>
        <CUSTOMER ID="B6"/>
    </SECURITY>
</BROADRIDGE>
<?xml version="1.0" encoding="UTF-8"?>
<BROADRIDGE>
    <SECURITY CUSIP="CUSIP1">
        <CUSTOMER ID="M1"/>
        <CUSTOMER ID="M2"/>
        <CUSTOMER ID="M3"/>
    </SECURITY>
    <SECURITY CUSIP="CUSIP3">
        <CUSTOMER ID="M4"/>
        <CUSTOMER ID="M5"/>
        <CUSTOMER ID="M6"/>
    </SECURITY>
    <SECURITY CUSIP="CUSIP2">
        <CUSTOMER ID="B4"/>
        <CUSTOMER ID="B5"/>
        <CUSTOMER ID="B6"/>
    </SECURITY>
</BROADRIDGE>

知道为什么不将两个文件中的客户合并到CUSIP中吗 CUSIP1?

保证参与给定转换的每个节点的generate-id()函数都不同。由于您在不同的文档上调用它,它们将不相同

您应该比较文档中CUSIP的字符串值,而不是它们的ID

如果您可以使用XSLT2.0(比1好得多),这将起作用

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output indent="yes"/>
        <xsl:template match="/MASTERFILE">
                <BROADRIDGE>
                        <xsl:variable name="securities" select="document(FILE)/BROADRIDGE/SECURITY"/>
                        <xsl:for-each select="distinct-values($securities/@CUSIP)">
                                <SECURITY>
                                        <xsl:attribute name="CUSIP">
                                                <xsl:value-of select="."/>
                                        </xsl:attribute>

                                        <xsl:for-each select="distinct-values($securities[@CUSIP = 'CUSIP1']/CUSTOMER/@ID)">
                                                <CUSTOMER>
                                                  <xsl:attribute name="ID">
                                                  <xsl:value-of select="."/>
                                                  </xsl:attribute>
                                                </CUSTOMER>
                                        </xsl:for-each>
                                </SECURITY>
                        </xsl:for-each>
                </BROADRIDGE>
        </xsl:template>
</xsl:stylesheet>

(请参阅我在OP上对“单向合并”的评论)以下是我对合并问题的(非常低效)解决方案:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:variable name="set1" select="document('file1.xml')/BROADRIDGE/SECURITY"/>
    <xsl:variable name="set2" select="document('file2.xml')/BROADRIDGE/SECURITY"/>

    <xsl:template match="/">
        <BROADRIDGE>
            <!-- walk over all relevant nodes -->
            <xsl:for-each select="$set1 | $set2">
                <xsl:variable name="position" select="position()"/>
                <xsl:variable name="cusip" select="@CUSIP"/>
                <!-- if we see this CUSIP for the first time, --> 
                <xsl:if test="count($nodes[position() &lt; $position][@CUSIP = $cusip])=0">
                    <SECURITY>                            
                        <xsl:attribute name="CUSIP"><xsl:value-of select="$cusip"/></xsl:attribute>
                        <!-- copy nodes from both sets with matching attribute -->
                        <xsl:copy-of select="$set1[@CUSIP = $cusip]/*"/>
                        <xsl:copy-of select="$set2[@CUSIP = $cusip]/*"/>
                    </SECURITY>
                </xsl:if>
            </xsl:for-each>
        </BROADRIDGE>
    </xsl:template>
</xsl:stylesheet>

请注意,样式表没有假设任何特定的文档-它只是将这两个文件作为变量加载。可以通过参数化要加载的XML文档的URL来改进xslt设计

要将合并应用于多个文档,可以创建一个文件,例如master.xml,该文件列出了要处理的所有文件,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="merge.xslt"?>
<files>
  <file>file1.xml</file>
  <file>file2.xml</file>
  ...
  <file>fileN.xml</file>    
</files>

file1.xml
file2.xml
...
fileN.xml
在file1.xml中,我有以下内容:

<?xml version='1.0' encoding='UTF-8'?>
<BROADRIDGE>
  <SECURITY CUSIP='CUSIP1' DESCRIPT='CUSIP1'>
    <CUSTOMER ID='M1'/>
    <CUSTOMER ID='M2'/>
    <CUSTOMER ID='M3'/>
  </SECURITY>
  <SECURITY CUSIP='CUSIP3' DESCRIPT='CUSIP3'>
    <CUSTOMER ID='M4'/>
    <CUSTOMER ID='M5'/>
    <CUSTOMER ID='M6'/>
  </SECURITY>
</BROADRIDGE>
<?xml version='1.0' encoding='UTF-8'?>
<BROADRIDGE>
  <SECURITY CUSIP='CUSIP1' DESCRIPT='CUSIP1'>
    <CUSTOMER ID='B1'/>
    <CUSTOMER ID='B2'/>
    <CUSTOMER ID='B3'/>
  </SECURITY>
  <SECURITY CUSIP='CUSIP2' DESCRIPT='CUSIP2'>
    <CUSTOMER ID='B4'/>
    <CUSTOMER ID='B5'/>
    <CUSTOMER ID='B6'/>
  </SECURITY>
</BROADRIDGE>

在file2.xml中,我有以下内容:

<?xml version='1.0' encoding='UTF-8'?>
<BROADRIDGE>
  <SECURITY CUSIP='CUSIP1' DESCRIPT='CUSIP1'>
    <CUSTOMER ID='M1'/>
    <CUSTOMER ID='M2'/>
    <CUSTOMER ID='M3'/>
  </SECURITY>
  <SECURITY CUSIP='CUSIP3' DESCRIPT='CUSIP3'>
    <CUSTOMER ID='M4'/>
    <CUSTOMER ID='M5'/>
    <CUSTOMER ID='M6'/>
  </SECURITY>
</BROADRIDGE>
<?xml version='1.0' encoding='UTF-8'?>
<BROADRIDGE>
  <SECURITY CUSIP='CUSIP1' DESCRIPT='CUSIP1'>
    <CUSTOMER ID='B1'/>
    <CUSTOMER ID='B2'/>
    <CUSTOMER ID='B3'/>
  </SECURITY>
  <SECURITY CUSIP='CUSIP2' DESCRIPT='CUSIP2'>
    <CUSTOMER ID='B4'/>
    <CUSTOMER ID='B5'/>
    <CUSTOMER ID='B6'/>
  </SECURITY>
</BROADRIDGE>

merge.xslt是早期版本的修改版本,现在可以处理数量可变的文件(master.xml中列出的文件):


运行此命令可获得以下输出:

<BROADRIDGE>
  <SECURITY CUSIP="CUSIP1">
    <CUSTOMER ID="M1"/>
    <CUSTOMER ID="M2"/>
    <CUSTOMER ID="M3"/>
    <CUSTOMER ID="B1"/>
    <CUSTOMER ID="B2"/>
    <CUSTOMER ID="B3"/>
  </SECURITY>
  <SECURITY CUSIP="CUSIP3">
    <CUSTOMER ID="M4"/>
    <CUSTOMER ID="M5"/>
    <CUSTOMER ID="M6"/>
  </SECURITY>
  <SECURITY CUSIP="CUSIP2">
    <CUSTOMER ID="B4"/>
    <CUSTOMER ID="B5"/>
    <CUSTOMER ID="B6"/>
  </SECURITY>
</BROADRIDGE>

要么你把这个问题弄得太复杂了,要么你还没有提到这个问题的其他方面:

<xsl:variable name="file1" select="document(/MASTERFILE/FILE[1])"/>
<xsl:variable name="file2" select="document(/MASTERFILE/FILE[2])"/>

<xsl:template match="/">
   <BROADRIDGE>
      <xsl:apply-templates select="$file1/BROADRIDGE/SECURITY"/>
      <xsl:copy-of select="$file2/BROADRIDGE/SECURITY[not(@CUISP=$file1/BROADRIDGE/SECURITY/@CUISP)]"/>
   </BROADRIDGE>
</xsl:template>

<xsl:template match="SECURITY">
   <SECURITY>
      <xsl:copy-of select="*"/>
      <xsl:copy-of select="$file2/BROADRIDGE/SECURITY[@CUSIP=current()/@CUSIP]/*"/>
   </SECURITY>
</xsl:template>


罗兰,谢谢你的例子。根据您发送的第一个代码,我开发了以下模板:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:variable name="nodes" select="document(/MASTERFILE/FILE)/BROADRIDGE/SECURITY"/>
    <xsl:template match="/">
        <BROADRIDGE>
            <!-- walk over all relevant nodes -->
            <xsl:for-each select="$nodes">
                <xsl:variable name="position" select="position()"/>
                <xsl:variable name="cusip" select="@CUSIP"/>
                <!-- if we see this CUSIP for the first time, --> 
                <xsl:if test="count($nodes[position() &lt; $position][@CUSIP = $cusip])=0">
                    <SECURITY>                            
                        <xsl:attribute name="CUSIP"><xsl:value-of select="$cusip"/></xsl:attribute>
                        <xsl:attribute name="DESCRIPT"><xsl:value-of select="@DESCRIPT"/></xsl:attribute>
                        <!-- copy nodes from both sets with matching attribute -->
                        <xsl:copy-of select="$nodes[@CUSIP = $cusip]/*"/>
                    </SECURITY>
                </xsl:if>
            </xsl:for-each>
        </BROADRIDGE>
    </xsl:template>

我只给document函数一个文件列表,这样它就创建了一个包含所有文件中所有安全节点的节点集。当我将其应用于以下xml时

<?xml version="1.0"?>
<MASTERFILE>
   <FILE>\file1.xml</FILE>
   <FILE>\file2.xml</FILE>
   <FILE>\file3.xml</FILE>
</MASTERFILE>

\file1.xml
\file2.xml
\file3.xml

它工作得很好。感谢您的示例

没有显示您的示例XML…我的意思是,加入它们的XML-不是file1和File2。那么,我对您的解决方案感兴趣。因为在我看来,你现在只合并了一种方式。我的意思是,您将获得文件中的所有安全元素,并将它们在CUSIP上与当前文档合并。但此解决方案将删除当前文档中不在文件中的任何CUSIP。如果我错了,请更正Jose:如果您使用Roland的解决方案,您应该将其标记为“已接受”答案。我认为您缺少变量节点的定义。我假设它的定义是:有了这个变化,我得到的是[…][…][…][…][…]所以它复制了这两个集合中出现的证券,以及他们所有的孩子。所以我还是错过了一些东西