Как объединить два XML-файла с соответствующим узлом
мне нужно найти способ присоединиться к двум XML-файлам, когда у них есть соответствующий узел. Насколько я понимаю, это можно сделать на многих языках... есть ли PHP или AJAX способ сделать это? Из других сообщений, поэтому я вижу решения XSLT.. этого я не понимаю. Это лучший / предпочтительный метод? Если да, то знаете о каких-либо полезных учебниках XSLT?
например, XML-1 похож на:
<FOO>
</A>
</B>
</C>
</D>
</FOO>
и XML-2 :
<FOO>
</B>
</E>
</FOO>
что было бы лучше всего подход для проверки, где <B>==<B>
затем добавить <E>
обновление
Ну, я не могу заставить это работать с моим гипотетическим примером и думал, что обновлю то, что я действительно делаю, чтобы увидеть, может ли кто-нибудь помочь мне понять это. Я пробовал методы снизу и другие, которые я нашел на так без везения.
реальная схема как :
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>
Я попытался создать слияние.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 очень новый для меня, поэтому я не уверен, что я делаю, и был бы очень признателен за руку, держащуюся за это.
3 ответов
это первоначальное преобразование немножко доработанное для того чтобы приспособить новые требования. Слияние выполняется путем проверки на file2.в XML элементы. Для текущего элемента в file1, детский элемент в file2 будет объединена только если нет в file1.
[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
копируется в Вывод, только если имеет совпадение вinput2.xml
трансформация (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
, затем обрабатывает все дочерние узлы, и это приводит к их копирования из шаблона идентичности. Наконец, все узлы, которые являются дочерними для любогоITEM
элемент из второго XML-документа которогоSTYLE_COLOR
child имеет то же строковое значение, что и строковое значениеSTYLE_COLOR
дочерний элемент текущего (согласованного) элемента также копируется (путем применения к ним шаблонов и в результате выбора и выполнения шаблона идентификатора), за исключением ребенок.обратите внимание, что пути к файлам двух pats передаются в качестве параметров преобразования, что делает его более гибким и способным работать с любыми двумя XML-файлы, без каких-либо изменений. Мы использовать XSLT
document()
функция для загрузки и анализа этих двух документов, чтобы они могли быть обработаны преобразованием xslt.обратите внимание, что нет
xsl:for-each
илиxsl:if
или любые другие условные инструкции XSLT используются в этой трансформации. Это приводит к упрощению и упрощению обслуживания и понимания кода.и, наконец, обратите внимание на использование и переопределение идентичности шаблон правила. Это самый фундаментальный и мощный шаблон дизайна XSLT.
XSLT довольно мощный, однако я должен признать, что я не так свободно с ним, поэтому дам вам sugestion для ручного преобразования:
print "<FOOCONTAINER>\n";
readfile($xml1file);
readfile($xml2file);
print "</FOOCONTAINER>\n";
все остальное вы можете легко выполнить в рамках дальнейшей обработки, так как это XML.
Edit: это работает только для первого XML, предлагаемого OP.