Узел клонирования XML в переполнении стека

Я должен клонировать узел XML и его дочерние элементы и добавить его к новому XML в специальном теге.

То есть:

Исходный XML:

<root>
<element>
<back>
<item1>ABC</item1>
<item2>DEF</item2>
<more>
<moreitem>GHI</moreitem>
</more
</back>
</element>
</root>

Целевой XML:

<root>
<base1>
<item1>FOO</item1>
<item2>BAR</item2>
<base2>
**<back>From source XML and all its childs here</back>**
</base2>
</base1>
<root>

0

Решение

DOMXpath::evaluate() позволяет вам выбирать узлы, используя выражения Xpath. DOMDocument::importNode() дублирует узел и импортирует узел в целевой документ. DOMNode::cloneNode() создайте дубликат узла для добавления в тот же документ. DOMNode::appendChild() позволяет добавить импортированный / клонированный узел.

$source = <<<'XML'
<root>
<element>
<back>
<item1>ABC</item1>
<item2>DEF</item2>
<more>
<moreitem>GHI</moreitem>
</more>
</back>
</element>
</root>
XML;

$target = <<<'XML'
<root>
<base1>
<item1>FOO</item1>
<item2>BAR</item2>
<base2>
</base2>
</base1>
</root>
XML;

$sourceDocument = new DOMDocument();
$sourceDocument->loadXml($source);
$sourceXpath = new DOMXpath($sourceDocument);

$targetDocument = new DOMDocument();
$targetDocument->loadXml($target);
$targetXpath = new DOMXpath($targetDocument);

foreach ($targetXpath->evaluate('/root/base1/base2[1]') as $targetNode) {
foreach ($sourceXpath->evaluate('/root/element/back') as $backNode) {
$targetNode->appendChild($targetDocument->importNode($backNode, TRUE));
}
}

echo $targetDocument->saveXml();

Выход:

<?xml version="1.0"?>
<root>
<base1>
<item1>FOO</item1>
<item2>BAR</item2>
<base2>
<back>
<item1>ABC</item1>
<item2>DEF</item2>
<more>
<moreitem>GHI</moreitem>
</more>
</back>
</base2>
</base1>
</root>
1

Другие решения

Конечно, вы можете использовать XSLT, родной язык программирования для реструктуризации XML-документов с учетом любых нюансов. В частности, здесь вам нужно извлечь XML-контент из внешнего исходного XML-файла. И PHP, как и другие языки общего назначения (Java, C #, Python, VB), поддерживают библиотеки для обработки XSLT.

XSLT (сохраните как файл .xsl или .xslt для использования в PHP ниже и убедитесь, что исходный и целевой XML-файлы находятся в одном каталоге)

<?xml version="1.0" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />

<!-- Identity Transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="back">
<back>
<xsl:copy-of select="document('Source.xml')"/>
</back>
</xsl:template>

</xsl:transform>

PHP (внешняя загрузка файлов XML и XSL, но может быть встроена в виде строки)

$destinationdoc = new DOMDocument();
$doc1->load('Destination.xml');

$xsl = new DOMDocument;
$xsl->load('XSLTScript.xsl');

// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);

// Transform XML source
$newXml = $proc->transformToXML($doc1);

// Save output to file
$xmlfile = 'FinalOutput.xml';
file_put_contents($xmlfile, $newXml);

ВЫХОД (используя ваш выше отправленный источник и назначение xml)

<?xml version="1.0" encoding="UTF-8"?>
<root>
<base1>
<item1>FOO</item1>
<item2>BAR</item2>
<base2>
<back>
<root>
<element>
<back>
<item1>ABC</item1>
<item2>DEF</item2>
<more>
<moreitem>GHI</moreitem>
</more>
</back>
</element>
</root>
</back>
</base2>
</base1>
</root>
2

Это простой способ сделать это:

$src = new DOMDocument();
$dst = new DOMDocument();

$src->loadXML($src_xml);
$dst->loadXML($dst_xml);

$back = $src->getElementsByTagName('back')->item(0);
$base = $dst->getElementsByTagName('base2')->item(0);

$base->appendChild( $dst->importNode( $back, true ) );
echo $dst->saveXML();
0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector