标识XML元素并使用PHP将父节点复制到外部XML文件
我正在用PHP解析一个XML文件(source.XML),需要识别标识XML元素并使用PHP将父节点复制到外部XML文件,php,xml,domdocument,Php,Xml,Domdocument,我正在用PHP解析一个XML文件(source.XML),需要识别节点包含元素的实例 一旦识别出该条目的整个父节点,就应该将其复制到单独的XML文件(destination.XML)中 复制完成后,应将节点从source.xml文件中删除 下面是source.xml文件的示例: <?xml version="1.0" encoding="utf-8"?> <root> <property> ... <rent>
节点包含
元素的实例
一旦识别出该条目的整个
父节点,就应该将其复制到单独的XML文件(destination.XML)中
复制完成后,应将
节点从source.xml文件中删除
下面是source.xml文件的示例:
<?xml version="1.0" encoding="utf-8"?>
<root>
<property>
...
<rent>
<term>long</term>
<freq>month</freq>
<price_peak>1234</price_peak>
<price_high>1234</price_high>
<price_medium>1234</price_medium>
<price_low>1234</price_low>
</rent>
...
</property>
</root>
我才刚刚开始了解DOMDocument及其用途,所以我显然在某个地方搞砸了,所以非常感谢您的帮助。非常感谢。困难在于您试图将节点从一个文档复制到另一个文档。您可以尝试重新创建节点,跨多个节点复制所有组件,但这是一项艰巨的工作(而且容易出错)。相反,您可以使用
importNode
将节点从一个文档导入到另一个文档。第二个参数表示复制所有子元素
然后从原始文档中删除元素就是让项目“从其父项中删除自身”,这听起来很奇怪,但这就是代码的工作方式
<?php
error_reporting ( E_ALL );
ini_set ( 'display_errors', 1 );
$destination = new DOMDocument;
$destination->preserveWhiteSpace = true;
$destination->loadXML('<?xml version="1.0" encoding="utf-8"?><root></root>');
$source = new DOMDocument;
$source->load('NewFile.xml');
$xp = new DOMXPath($source);
$destRoot = $destination->getElementsByTagName("root")->item(0);
foreach ($xp->query('/root/property[rent]') as $item) {
$newItem = $destination->importNode($item, true);
$destRoot->appendChild($newItem);
$item->parentNode->removeChild($item);
}
echo "Source:".$source->saveXML();
$destination->formatOutput = true;
echo "destination:".$destination->saveXml();
load('NewFile.xml');
$xp=新的DOMXPath($source);
$destRoot=$destination->getElementsByTagName(“根”)->项(0);
foreach($xp->query('/root/property[rent]')作为$item){
$newItem=$destination->importNode($item,true);
$desroot->appendChild($newItem);
$item->parentNode->removeChild($item);
}
echo“Source:”.$Source->saveXML();
$destination->formatOutput=true;
echo“destination:”.$destination->saveXml();
对于目的地,我使用basic
元素初始化它,然后从那里添加内容。您想获得类似的内容吗?希望这有助于:
$inXmlFile = getcwd() . "/source.xml";
$inXmlString = file_get_contents($inXmlFile);
$outXmlFile = getcwd() . "/destination.xml";
$outXmlString = file_get_contents($outXmlFile);
$sourceDOMDocument = new DOMDocument;
$sourceDOMDocument->loadXML($inXmlString);
$sourceRoot = null;
foreach ($sourceDOMDocument->childNodes as $childNode) {
if(strcmp($childNode->nodeName, "root") == 0) {
$sourceRoot = $childNode;
break;
}
}
$destDOMDocument = new DOMDocument;
$destDOMDocument->loadXML($outXmlString);
$destRoot = null;
foreach ($destDOMDocument->childNodes as $childNode) {
if(strcmp($childNode->nodeName, "root") == 0) {
$destRoot = $childNode;
break;
}
}
$xmlStructure = simplexml_load_string($inXmlString);
$domProperty = dom_import_simplexml($xmlStructure->property);
$rents = $domProperty->getElementsByTagName('rent');
if(($rents != null) && (count($rents) > 0)) {
$destRoot->appendChild($destDOMDocument->importNode($domProperty->cloneNode(true), true));
$destDOMDocument->save($outXmlFile);
$sourceRoot->removeChild($sourceRoot->getElementsByTagName('property')->item(0));
$sourceDOMDocument->save($inXmlFile);
}
考虑运行两个XSLT转换:一个在目标中添加
节点,另一个从源中删除这些节点。作为背景,是一种特殊用途的语言,设计用于转换XML文件,甚至可以维护document()
函数来解析同一文件夹或子文件夹中的外部XML文件
PHP可以使用其类运行XSLT1.0脚本(请确保在.ini文件中启用扩展名)。使用这种方法,不需要if
逻辑或foreach
循环
XSLT脚本
PropertyRentAdd.xsl(确保source.xml和XSLT位于同一文件夹中)
输入(示例演示,其他标签显示内容不受影响)
source.xml
<?xml version="1.0" encoding="utf-8"?>
<root>
<property>
<rent>
<term>long</term>
<freq>month</freq>
<price_peak>1234</price_peak>
<price_high>1234</price_high>
<price_medium>1234</price_medium>
<price_low>1234</price_low>
</rent>
</property>
<property>
<rent>
<term>short</term>
<freq>month</freq>
<price_peak>7890</price_peak>
<price_high>7890</price_high>
<price_medium>7890</price_medium>
<price_low>7890</price_low>
</rent>
</property>
<property>
<web_site>stackoverflow</web_site>
<general_purpose>php</general_purpose>
</property>
<property>
<web_site>stackoverflow</web_site>
<special_purpose>xsl</special_purpose>
</property>
</root>
长的
月
1234
1234
1234
1234
短的
月
7890
7890
7890
7890
栈溢出
php
栈溢出
xsl
destination.xml
<?xml version="1.0" encoding="utf-8"?>
<root>
<original_data>
<test1>ABC</test1>
<test2>123</test2>
</original_data>
<original_data>
<test1>XYZ</test1>
<test2>789</test2>
</original_data>
</root>
基础知识
123
XYZ
789
输出(PHP运行后)
source.xml
<?xml version="1.0"?>
<root>
<property>
<web_site>stackoverflow</web_site>
<general_purpose>php</general_purpose>
</property>
<property>
<web_site>stackoverflow</web_site>
<special_purpose>xsl</special_purpose>
</property>
</root>
栈溢出
php
栈溢出
xsl
destination.xml(在底部追加新节点)
基础知识
123
XYZ
789
长的
月
1234
1234
1234
1234
短的
月
7890
7890
7890
7890
非常感谢。这非常有效,除了源输出和目标输出都不会保存到仅输出到控制台的文件中。我试着摆弄它来生成文件,但没有结果。如何将$source输出到newsource.xml和$destination输出到destination.xml?没关系,我知道了:)。我尝试的是$source->saveXML(“final_source.xml”),而不是直接的$source->save(“final_source.xml”)。再次感谢。谢谢你的工作冻糕,它非常详细,我一定会调查。然而,就目前而言,Nigel Ren给出的答案更符合我的工作流程。再次感谢。
// Set current path
$cd = dirname(__FILE__);
// Load the XML and XSLT files
$doc = new DOMDocument();
$doc->load($cd.'/destination.xml');
$xsl = new DOMDocument;
$xsl->load($cd.'/PropertRentAdd.xsl');
// Transform the destination xml
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
$newXml = $proc->transformToXML($xml);
// Save output to file, overwriting original
file_put_contents($cd.'/destination.xml', $newXml);
// Load the XML and XSLT files
$doc = new DOMDocument();
$doc->load($cd.'/source.xml');
$xsl = new DOMDocument;
$xsl->load($cd.'/PropertRentRemove.xsl');
// Transform the source xml
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
$newXml = $proc->transformToXML($xml);
// Save output overwriting original file
file_put_contents($cd.'/source.xml', $newXml);
<?xml version="1.0" encoding="utf-8"?>
<root>
<property>
<rent>
<term>long</term>
<freq>month</freq>
<price_peak>1234</price_peak>
<price_high>1234</price_high>
<price_medium>1234</price_medium>
<price_low>1234</price_low>
</rent>
</property>
<property>
<rent>
<term>short</term>
<freq>month</freq>
<price_peak>7890</price_peak>
<price_high>7890</price_high>
<price_medium>7890</price_medium>
<price_low>7890</price_low>
</rent>
</property>
<property>
<web_site>stackoverflow</web_site>
<general_purpose>php</general_purpose>
</property>
<property>
<web_site>stackoverflow</web_site>
<special_purpose>xsl</special_purpose>
</property>
</root>
<?xml version="1.0" encoding="utf-8"?>
<root>
<original_data>
<test1>ABC</test1>
<test2>123</test2>
</original_data>
<original_data>
<test1>XYZ</test1>
<test2>789</test2>
</original_data>
</root>
<?xml version="1.0"?>
<root>
<property>
<web_site>stackoverflow</web_site>
<general_purpose>php</general_purpose>
</property>
<property>
<web_site>stackoverflow</web_site>
<special_purpose>xsl</special_purpose>
</property>
</root>
<?xml version="1.0"?>
<root>
<original_data>
<test1>ABC</test1>
<test2>123</test2>
</original_data>
<original_data>
<test1>XYZ</test1>
<test2>789</test2>
</original_data>
<property>
<rent>
<term>long</term>
<freq>month</freq>
<price_peak>1234</price_peak>
<price_high>1234</price_high>
<price_medium>1234</price_medium>
<price_low>1234</price_low>
</rent>
</property>
<property>
<rent>
<term>short</term>
<freq>month</freq>
<price_peak>7890</price_peak>
<price_high>7890</price_high>
<price_medium>7890</price_medium>
<price_low>7890</price_low>
</rent>
</property>
</root>