Php 如何将现有元素从XML文件B添加到XML文件A

Php 如何将现有元素从XML文件B添加到XML文件A,php,xml,dom,server,simplexml,Php,Xml,Dom,Server,Simplexml,我有2个XML文件 我试图从XML文件B中获取数据并将其添加到XML文件A中。我想首先向XML文件A中添加一个空的子元素,然后在该子元素中,我想从XML文件B中添加数据(在本例中,是animalchild元素)。我想通过SimpleXML或DOMDocument实现这一点。我一直被困在这个问题上。任何帮助都会很好 personinfo.xml

我有2个XML文件

我试图从XML文件B中获取数据并将其添加到XML文件A中。我想首先向XML文件A中添加一个空的子元素,然后在该子元素中,我想从XML文件B中添加数据(在本例中,是
animal
child元素)。我想通过SimpleXML或DOMDocument实现这一点。我一直被困在这个问题上。任何帮助都会很好

personinfo.xml
<personinfo>
    <personN number="1">
        <personL letter="A">
            <fullname>
                <firstname>Summer</firstname>
                <lastname>Smith</lastname>
            </fullname>
            <favourites>
                <color>pink</color>
            </favourites>
        </personL>  
    </personN>

    <personN number="2">
        <personL letter="B">
            <fullname>
                <firstname>Autumn</firstname>
                <lastname>Smith</lastname>
            </fullname>
            <favourites>
                <color>blue</color>
            </favourites>
        </personL>  
    </personN>
</personinfo>
期望输出

<personinfo>
    <personN number="1">
        <personL letter="A">
            <fullname>
                <firstname>Summer</firstname>
                <lastname>Smith</lastname>
            </fullname>
            <favourites>
                <color>pink</color>
            </favourites>
            <favourites>
                <color>cat</color>
            </favourites>
        </personL>  
    </personN>

    <personN number="2">
        <personL letter="B">
            <fullname>
                <firstname>Autumn</firstname>
                <lastname>Smith</lastname>
            </fullname>
            <favourites>
                <color>blue</color>
            </favourites>
            <favourites>
                <color>dog</color>
            </favourites>
        </personL>  
    </personN>
</personinfo>

夏天
史密斯
粉红色
猫
秋
史密斯
蓝色
狗

这在DOM中更容易,因为您可以访问节点,并可以将它们从一个文档复制到另一个文档。使用Xpath获取文档的某些部分

// load the XML into DOM document and create Xpath instances
$personsDocument = new DOMDocument;
$personsDocument->preserveWhiteSpace = FALSE;
$personsDocument->loadXML($xmlPersons);
$personsXpath = new DOMXpath($personsDocument);

$favoritesDocument = new DOMDocument;
$favoritesDocument->preserveWhiteSpace = FALSE;
$favoritesDocument->loadXML($xmlFavorites);
$favoritesXpath = new DOMXpath($favoritesDocument);

// iterate the personN nodes in the favorties XML
foreach ($favoritesXpath->evaluate('.//personN') as $personFavorites) {
    $personId = (int)$personFavorites->getAttribute('number');
    // find the matching personL node in the persons XML
    foreach ($personsXpath->evaluate('.//personN[@number='.$personId.']/personL') as $personNode) {
        // check if it has a 'favourites' child already
        $favoritesNode = $personsXpath->evaluate('favourites', $personNode)->item(0);
        if (!$favoritesNode) {
            // otherwise create one
            $favoritesNode = $personNode->appendChild(
                $personsDocument->createElement('favourites')
            );
        }
        // now iterate the different favorites of a person
        foreach ($personFavorites->childNodes as $favorite) {
            // import and add
            $favoritesNode->appendChild($personsDocument->importNode($favorite, TRUE));
        }
    }
}

$personsDocument->formatOutput = TRUE;
echo $personsDocument->saveXML();
输出:

<?xml version="1.0"?>
<personinfo>
  <personN number="1">
    <personL letter="A">
      <fullname>
        <firstname>Summer</firstname>
        <lastname>Smith</lastname>
      </fullname>
      <favourites>
        <color>pink</color>
        <animal>cat</animal>
      </favourites>
    </personL>
  </personN>
  <personN number="2">
    <personL letter="B">
      <fullname>
        <firstname>Autumn</firstname>
        <lastname>Smith</lastname>
      </fullname>
      <favourites>
        <color>blue</color>
        <animal>dog</animal>
      </favourites>
    </personL>
  </personN>
</personinfo>

据我所知,纯SimpleXMLElement不允许从另一个现成文档导入节点,但DOMDocument允许

幸运的是,两者都能很好地协同工作,SimpleXMLElement可以“转换”为DOMNode,反之亦然

这就是为什么

下面是一个与您问题中的示例相关的示例,但不是使用
SimpleXML::addChild()
导入DOM,然后将(再次导入的)子节点添加到DomeElement节点:

$parent = dom_import_simplexml($newFave); # [1]
$parent->appendChild( # [2]
    $parent->ownerDocument->importNode(dom_import_simplexml($animal), true) # [3]
);

echo $personXML->asXML(); # [4]
  • 父元素创建DOM节点
  • 在DOM父节点上追加子节点
  • 创建并导入动物最喜爱的DOM节点。需要首先将节点导入到父文档,因为它是不同DOMDocument的一部分,并且只有当节点是同一文档的一部分时,才能添加子节点
  • 使用SimpleXMLElement输出
  • 结果(以难看的字体)如下所示:

    ...
            <personL letter="A">
                <fullname>
                    <firstname>Summer</firstname>
                    <lastname>Smith</lastname>
                </fullname>
                <favourites>
                    <color>pink</color>
                </favourites>
            <favourites><animal>cat</animal></favourites></personL>
                   ^       ^
                   |       |
                   |   $animal = $faveXML->personN[0]->animal;
                   |   $parent->ownerDocument
                   |       ->importNode(dom_import_simplexml($animal), true)
                   |
                   |
    
       $newFave = $personXML->personN->personL[0]->addChild("favourites");
    ...
    
    • 进一步参考:
    foreach ($personsXpath->evaluate('.//personN[@number='.$personId.']/personL') as $personNode) {
        //create 'favourites' child
        $favoritesNode = $personNode->appendChild(
            $personsDocument->createElement('favourites')
        );
        foreach ($personFavorites->childNodes as $favorite) {
        //...
    
    $parent = dom_import_simplexml($newFave); # [1]
    $parent->appendChild( # [2]
        $parent->ownerDocument->importNode(dom_import_simplexml($animal), true) # [3]
    );
    
    echo $personXML->asXML(); # [4]
    
    ...
            <personL letter="A">
                <fullname>
                    <firstname>Summer</firstname>
                    <lastname>Smith</lastname>
                </fullname>
                <favourites>
                    <color>pink</color>
                </favourites>
            <favourites><animal>cat</animal></favourites></personL>
                   ^       ^
                   |       |
                   |   $animal = $faveXML->personN[0]->animal;
                   |   $parent->ownerDocument
                   |       ->importNode(dom_import_simplexml($animal), true)
                   |
                   |
    
       $newFave = $personXML->personN->personL[0]->addChild("favourites");
    ...
    
    foreach ($faveXML->xpath('./personN[*]') as $person) {
        foreach ($personXML->xpath(
            sprintf('./personN[@number = "%d"]/*/favourites[1]', $person['number'])
        ) as $favourites) {
            $parent = dom_import_simplexml($favourites);
            $parent->appendChild(
                $parent->ownerDocument->importNode(dom_import_simplexml($person->children()[0]), true)
            );
        }
    };