如何将 XML 文件 B 中的现有元素添加到 XML 文件 A
How to add existing elements from XML file B to XML file A
我有 2 个 XML 文件。
我正在尝试从 XML 文件 B 中获取数据并将其添加到 XML 文件 A。我想先添加一个空的 child 到 XML 文件A,然后在 child 中,我想添加来自 XML 文件 B 的数据(在本例中为 animal
child 元素)。我想通过 SimpleXML 或 DOMDocument 来实现。我一直坚持这一点。任何帮助都会很棒!
personinfo.xml < XML 文件 A
<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>
favouritesinfo.xml < XML 文件 B
<favouritesinfo>
<personN number="1">
<animal>cat</animal>
</personN>
<personN number="2">
<animal>dog</animal>
</personN>
</favouritesinfo>
这可能吗?如果是这样,我可以通过 XML DOM Document 或 SimpleXML 来做到这一点吗?
我尝试通过单独的 PHP 文件以这种方式进行操作,但它不会 work/do 任何与 SimpleXML
$personXML = simplexml_load_file("personinfo.xml");
$faveXML = simplexml_load_file("favouritesinfo.xml");
$animal=$faveXML->personN[0]->animal;
$newFave=$personXML->personN->personL[0]->addChild("favourites");
$favourites->addChild($animal);
$personXML->asXML();
期望的输出
<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>
为每个收藏添加一个favourites
parent 没有多大意义。所以我在我的示例中添加了一个检查。如果你真的想要 parent 个节点,你可以删除它:
foreach ($personsXpath->evaluate('.//personN[@number='.$personId.']/personL') as $personNode) {
//create 'favourites' child
$favoritesNode = $personNode->appendChild(
$personsDocument->createElement('favourites')
);
foreach ($personFavorites->childNodes as $favorite) {
//...
据我所知,纯 SimpleXMLElement 不允许开箱即用地从另一个文档导入节点,但 DOMDocument 可以。
幸运的是,两者可以很好地协同工作,一个简单XML元素可以"turned"变成一个DOM节点和vice-versa。
这就是 dom_import_simplexml()
function 的用途。
这是一个与您在问题中的示例相关的示例,但不是使用 SimpleXML::addChild()
导入 DOM 然后将(再次导入) child 添加到DOM元素节点:
$parent = dom_import_simplexml($newFave); # [1]
$parent->appendChild( # [2]
$parent->ownerDocument->importNode(dom_import_simplexml($animal), true) # [3]
);
echo $personXML->asXML(); # [4]
- 为
<favourites>
parent 元素创建一个 DOM 节点
- 在 DOM parent 节点上附加 child
- 创建并导入最喜欢的动物 DOM 节点。该节点需要首先导入到 parent 文档中,因为它是 不同的 DOM 文档的一部分,并且只有在以下情况下才可能添加 child 节点节点是同一文档的一部分。
- 使用简单XML元素
输出
结果(丑陋的打印)如下:
...
<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");
...
我希望这很容易理解。这是@ThW 在他的回答中提出的一些建议,但仅在 SimpleXMLElement 无法完成工作的部分使用 DOMDocument。
我也喜欢他的建议,不要一次又一次地添加收藏夹元素。因此,为了获得一种更动态的方法来通过这两个 XML 文档中的人员编号添加人员的收藏夹,让我们添加一些 Xpath 到组合中:
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)
);
}
};
我有 2 个 XML 文件。
我正在尝试从 XML 文件 B 中获取数据并将其添加到 XML 文件 A。我想先添加一个空的 child 到 XML 文件A,然后在 child 中,我想添加来自 XML 文件 B 的数据(在本例中为 animal
child 元素)。我想通过 SimpleXML 或 DOMDocument 来实现。我一直坚持这一点。任何帮助都会很棒!
personinfo.xml < XML 文件 A
<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>
favouritesinfo.xml < XML 文件 B
<favouritesinfo>
<personN number="1">
<animal>cat</animal>
</personN>
<personN number="2">
<animal>dog</animal>
</personN>
</favouritesinfo>
这可能吗?如果是这样,我可以通过 XML DOM Document 或 SimpleXML 来做到这一点吗?
我尝试通过单独的 PHP 文件以这种方式进行操作,但它不会 work/do 任何与 SimpleXML
$personXML = simplexml_load_file("personinfo.xml");
$faveXML = simplexml_load_file("favouritesinfo.xml");
$animal=$faveXML->personN[0]->animal;
$newFave=$personXML->personN->personL[0]->addChild("favourites");
$favourites->addChild($animal);
$personXML->asXML();
期望的输出
<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>
为每个收藏添加一个favourites
parent 没有多大意义。所以我在我的示例中添加了一个检查。如果你真的想要 parent 个节点,你可以删除它:
foreach ($personsXpath->evaluate('.//personN[@number='.$personId.']/personL') as $personNode) {
//create 'favourites' child
$favoritesNode = $personNode->appendChild(
$personsDocument->createElement('favourites')
);
foreach ($personFavorites->childNodes as $favorite) {
//...
据我所知,纯 SimpleXMLElement 不允许开箱即用地从另一个文档导入节点,但 DOMDocument 可以。
幸运的是,两者可以很好地协同工作,一个简单XML元素可以"turned"变成一个DOM节点和vice-versa。
这就是 dom_import_simplexml()
function 的用途。
这是一个与您在问题中的示例相关的示例,但不是使用 SimpleXML::addChild()
导入 DOM 然后将(再次导入) child 添加到DOM元素节点:
$parent = dom_import_simplexml($newFave); # [1]
$parent->appendChild( # [2]
$parent->ownerDocument->importNode(dom_import_simplexml($animal), true) # [3]
);
echo $personXML->asXML(); # [4]
- 为
<favourites>
parent 元素创建一个 DOM 节点 - 在 DOM parent 节点上附加 child
- 创建并导入最喜欢的动物 DOM 节点。该节点需要首先导入到 parent 文档中,因为它是 不同的 DOM 文档的一部分,并且只有在以下情况下才可能添加 child 节点节点是同一文档的一部分。
- 使用简单XML元素 输出
结果(丑陋的打印)如下:
...
<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");
...
我希望这很容易理解。这是@ThW 在他的回答中提出的一些建议,但仅在 SimpleXMLElement 无法完成工作的部分使用 DOMDocument。
我也喜欢他的建议,不要一次又一次地添加收藏夹元素。因此,为了获得一种更动态的方法来通过这两个 XML 文档中的人员编号添加人员的收藏夹,让我们添加一些 Xpath 到组合中:
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)
);
}
};