我需要找到一种方法来连接两个XML文件,当它们具有匹配的节点时。从我收集的内容可以用许多不同的语言来实现...有没有PHP或AJAX方法来做到这一点?从SO上的其他帖子我看到XSLT解决方案..我真的不知道。这是最好/首选的方法吗?如果是这样,知道任何有用的XSLT教程吗?
例如,XML-1就像:
<FOO>
</A>
</B>
</C>
</D>
</FOO>
和XML-2:
<FOO>
</B>
</E>
</FOO>
检查<B>==<B>
然后添加<E>
嗯,我不能用这个假设的例子来解决这个问题,并且认为我会更新我正在做的事情,看看是否有人可以帮助我解决这个问题。我已经尝试了下面的方法以及我在SO上找到的其他方法,但没有运气。
真正的架构如下:
file1.xml
<?xml version="1.0"?>
<DATA>
<ITEM>
<PRODUCT_TYPE>simple</PRODUCT_TYPE>
<STYLE_COLOR>1524740007</STYLE_COLOR>
<SHORT_DESCRIPTION>Black Shoe</SHORT_DESCRIPTION>
<CLASS_NAME>FOOTWEAR</CLASS_NAME>
<STATUS>Disabled</STATUS>
</ITEM>
...
</DATA>
file2.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="merge.xsl" ?>
<DATA>
<ITEM>
<STYLE_COLOR>1524740007</STYLE_COLOR>
<NEXT_ARRIVAL>2011-08-05</NEXT_ARRIVAL>
</ITEM>
....
</DATA>
我需要弄清楚的是生成一个新的XML文件,它将这些节点与相同的SYTLE_COLOR合并,如下所示:
<DATA>
<ITEM>
<PRODUCT_TYPE>simple</PRODUCT_TYPE>
<STYLE_COLOR>1524740007</STYLE_COLOR>
<SHORT_DESCRIPTION>Black Shoe</SHORT_DESCRIPTION>
<CLASS_NAME>FOOTWEAR</CLASS_NAME>
<NEXT_ARRIVAL>2011-08-05</NEXT_ARRIVAL>
<STATUS>Disabled</STATUS>
</ITEM>
我尝试创建一个类似于:
的merge.xsl<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="ISO-8859-1" indent="yes" />
<xsl:output indent="yes"/>
<xsl:variable name="with" select="'file-2.xml'" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="scene">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
<xsl:variable name="info" select="document($with)/DATA/ITEM[STYLE_COLOR=current()/STYLE_COLOR]/." />
<xsl:for-each select="$info/*">
<xsl:if test="name()!='STYLE_COLOR'">
<xsl:copy-of select="." />
</xsl:if>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:transform>
我也试过像这样的合并:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:variable name="input2" select="document('file-2.xml')/DATA/ITEM"/>
<xsl:template match="STYLE_COLOR">
<xsl:copy>
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:choose>
<xsl:when test="$input2/*[name()=name(current())]">
<xsl:copy-of select="$input2/*"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
这两种方法都不起作用..对不起XSLT对我来说是一个新手,所以我不确定我在做什么,并且真的很感激一些人持有这个。
答案 0 :(得分:5)
这是原始转换略微修改以适应新要求。通过检查 file2.xml 元素来执行合并。对于 file1 中的当前ITEM,如果 file1 中不存在 file2 中的子项目将合并
[XSLT 1.0]
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="input2" select="document('test_input2.xml')/DATA"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ITEM">
<xsl:variable name="item" select="
$input2/ITEM[STYLE_COLOR=current()/STYLE_COLOR]"/>
<xsl:variable name="ITEM" select="."/>
<xsl:if test="$item">
<xsl:copy>
<xsl:for-each select="$item/*">
<xsl:if test="count($ITEM/*[name()=name(current())])=0">
<xsl:copy-of select="." />
</xsl:if>
</xsl:for-each>
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
应用于此input1.xml
:
<DATA>
<ITEM>
<PRODUCT_TYPE>simple</PRODUCT_TYPE>
<STYLE_COLOR>1524740007</STYLE_COLOR>
<SHORT_DESCRIPTION>Black Shoe</SHORT_DESCRIPTION>
<CLASS_NAME>FOOTWEAR</CLASS_NAME>
<STATUS>Disabled</STATUS>
</ITEM>
<ITEM>
<PRODUCT_TYPE>simple</PRODUCT_TYPE>
<STYLE_COLOR>1524740008</STYLE_COLOR>
<SHORT_DESCRIPTION>Black Shoe</SHORT_DESCRIPTION>
<CLASS_NAME>FOOTWEAR</CLASS_NAME>
<STATUS>Disabled</STATUS>
</ITEM>
<ITEM>
<PRODUCT_TYPE>simple</PRODUCT_TYPE>
<STYLE_COLOR>777</STYLE_COLOR>
<SHORT_DESCRIPTION>Black Shoe</SHORT_DESCRIPTION>
<CLASS_NAME>FOOTWEAR</CLASS_NAME>
<STATUS>Disabled</STATUS>
</ITEM>
</DATA>
和input2.xml
合并,生成:
<DATA>
<ITEM>
<STYLE_COLOR>1524740007</STYLE_COLOR>
<NEXT_ARRIVAL>2011-08-05</NEXT_ARRIVAL>
<CLASS_NAME>XXX</CLASS_NAME>
<OTHER>YYY</OTHER>
</ITEM>
<ITEM>
<STYLE_COLOR>1524740008</STYLE_COLOR>
<NEXT_ARRIVAL>2011-08-05</NEXT_ARRIVAL>
</ITEM>
</DATA>
产生
<DATA>
<ITEM>
<NEXT_ARRIVAL>2011-08-05</NEXT_ARRIVAL>
<OTHER>YYY</OTHER>
<PRODUCT_TYPE>simple</PRODUCT_TYPE>
<STYLE_COLOR>1524740007</STYLE_COLOR>
<SHORT_DESCRIPTION>Black Shoe</SHORT_DESCRIPTION>
<CLASS_NAME>FOOTWEAR</CLASS_NAME>
<STATUS>Disabled</STATUS>
</ITEM>
<ITEM>
<NEXT_ARRIVAL>2011-08-05</NEXT_ARRIVAL>
<PRODUCT_TYPE>simple</PRODUCT_TYPE>
<STYLE_COLOR>1524740008</STYLE_COLOR>
<SHORT_DESCRIPTION>Black Shoe</SHORT_DESCRIPTION>
<CLASS_NAME>FOOTWEAR</CLASS_NAME>
<STATUS>Disabled</STATUS>
</ITEM>
</DATA>
请注意:
input1.xml
中的ITEM仅在input2.xml
答案 1 :(得分:1)
此转化(问题中提供的c:/temp/file1.xml
和c:/temp/file2.xml
):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pDoc1" select="'file:///c:/temp/file1.xml'"/>
<xsl:variable name="vDoc1" select="document($pDoc1)"/>
<xsl:param name="pDoc2" select="'file:///c:/temp/file2.xml'"/>
<xsl:variable name="vDoc2" select="document($pDoc2)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="$vDoc1/node()"/>
</xsl:template>
<xsl:template match="ITEM">
<ITEM>
<xsl:apply-templates/>
<xsl:apply-templates select=
"$vDoc2/*/ITEM
[STYLE_COLOR = current()/STYLE_COLOR]
/node()[not(self::STYLE_COLOR)]
"/>
</ITEM>
</xsl:template>
</xsl:stylesheet>
应用于任何XML文档(未使用/忽略)时,会生成所需的正确结果:
<DATA>
<ITEM xmlns:xs="http://www.w3.org/2001/XMLSchema">
<PRODUCT_TYPE>simple</PRODUCT_TYPE>
<STYLE_COLOR>1524740007</STYLE_COLOR>
<SHORT_DESCRIPTION>Black Shoe</SHORT_DESCRIPTION>
<CLASS_NAME>FOOTWEAR</CLASS_NAME>
<STATUS>Disabled</STATUS>
<NEXT_ARRIVAL>2011-08-05</NEXT_ARRIVAL>
</ITEM> ...
</DATA>
<强>解释强>:
首先我们处理(应用模板)第一个XML文档的节点。
标识规则/模板按原样复制每个节点。
有一个模板会覆盖身份规则。此模板匹配名为ITEM
的任何元素。它创建一个名为ITEM
的元素,然后处理所有子节点,这会导致通过身份模板复制它们。最后,作为来自第二个XML文档中任何ITEM
元素的子节点的所有节点,其STYLE_COLOR
子节点具有与当前(匹配)的STYLE_COLOR
子节点的字符串值相同的字符串值元素也被复制(通过将模板应用于它们以及选择和执行身份模板的结果),STYLE_COLOR
子项本身除外。
请注意,两个pats的文件路径作为参数传递给转换,这使其更灵活,能够处理任何两个XML文件 - 无需任何修改。我们使用XSLT document()
函数来加载和解析这两个文档,以便它们可以通过xslt转换进行处理。
请注意,此转换中未使用xsl:for-each
或xsl:if
或任何其他XSLT条件指令。这样可以更简单,更易于维护和理解代码。
最后,请注意身份规则/模板的使用和覆盖。这是最基本和最强大的XSLT设计模式。
答案 2 :(得分:-1)
XSLT功能非常强大,但是我必须承认我并不是那么流利,所以会让你对手动转换有所了解:
print "<FOOCONTAINER>\n";
readfile($xml1file);
readfile($xml2file);
print "</FOOCONTAINER>\n";
您可以在进一步处理中轻松完成其他任何操作,因为这是XML。
编辑:这仅适用于OP提供的第一个XML。