PHP: 按属性从 xml 中删除节点
PHP: remove node from xml by attribute
假设我有这样一个 xml:
<products>
<product id="1">
<name>aaa</name>
<producturl>aaa</producturl>
<bigimage>aaa</bigimage>
<description>aaa</description>
<price>aaa</price>
<categoryid1>aaa</categoryid1>
<instock>aaa</instock>
</product>
<product id="2">
<name>aaa</name>
<producturl>aaa</producturl>
<bigimage>aaa</bigimage>
<description>aaa</description>
<price>aaa</price>
<categoryid1>aaa</categoryid1>
<instock>aaa</instock>
</product>
</products>
如果这个属性在数组中,我需要根据 id 属性删除某些节点。
我尝试了不同的方法,但 xml 总是输出原始的!
到目前为止我的代码:
<?php header("Content-type: text/xml");
$url="http://www.aaa.it/aaa.xml";
$url=file_get_contents($url);
$array=array("1","4","5");
$doc=new SimpleXMLElement($url);
foreach($doc->product as $product){
if(!in_array($product['id'],$array)){
$dom=dom_import_simplexml($product);
$dom->parentNode->removeChild($dom);
// unset($doc->product->$product);
}
}
echo $doc->asXml(); ?>
非常感谢大家。
考虑部分 XPath 和 XSLT 解决方案,两者都是 Extensible Stylesheet Family. XPath is first used to retrieve all current product ids which is then compared with current array of ids to keep using array_diff 中的兄弟。然后根据这些不匹配的 ID 迭代构建 XSLT 以删除节点。在 XSLT 中删除节点只需要一个空模板匹配。
// Load the XML source
header("Content-type: text/xml");
$url="http://www.aaa.it/aaa.xml";
$url=file_get_contents($url);
$doc=new SimpleXMLElement($url);
// Retrieve all XML product ids with XPath
$xpath = $doc->xpath("//product/@id");
$xmlids = [];
foreach($xpath as $item => $value){ $xmlids[] = (string)$value; }
// Compare difference with $array
$array = array("1","4","5");
$removeids = array_diff($xmlids, $array);
// Dynamically build XSLT string for each resulting id
foreach($removeids as $id){
$xslstr='<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="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="product[@id=\''.$id.'\']"/>
</xsl:transform>';
$xsl = new SimpleXMLElement($xslstr);
// Configure the transformer and run
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
$newXML = $proc->transformToXML($doc);
// Adjust $doc object with each loop
$doc = new SimpleXMLElement($newXML);
}
// Echo Output
echo $doc->asXML();
假设我有这样一个 xml:
<products>
<product id="1">
<name>aaa</name>
<producturl>aaa</producturl>
<bigimage>aaa</bigimage>
<description>aaa</description>
<price>aaa</price>
<categoryid1>aaa</categoryid1>
<instock>aaa</instock>
</product>
<product id="2">
<name>aaa</name>
<producturl>aaa</producturl>
<bigimage>aaa</bigimage>
<description>aaa</description>
<price>aaa</price>
<categoryid1>aaa</categoryid1>
<instock>aaa</instock>
</product>
</products>
如果这个属性在数组中,我需要根据 id 属性删除某些节点。
我尝试了不同的方法,但 xml 总是输出原始的!
到目前为止我的代码:
<?php header("Content-type: text/xml");
$url="http://www.aaa.it/aaa.xml";
$url=file_get_contents($url);
$array=array("1","4","5");
$doc=new SimpleXMLElement($url);
foreach($doc->product as $product){
if(!in_array($product['id'],$array)){
$dom=dom_import_simplexml($product);
$dom->parentNode->removeChild($dom);
// unset($doc->product->$product);
}
}
echo $doc->asXml(); ?>
非常感谢大家。
考虑部分 XPath 和 XSLT 解决方案,两者都是 Extensible Stylesheet Family. XPath is first used to retrieve all current product ids which is then compared with current array of ids to keep using array_diff 中的兄弟。然后根据这些不匹配的 ID 迭代构建 XSLT 以删除节点。在 XSLT 中删除节点只需要一个空模板匹配。
// Load the XML source
header("Content-type: text/xml");
$url="http://www.aaa.it/aaa.xml";
$url=file_get_contents($url);
$doc=new SimpleXMLElement($url);
// Retrieve all XML product ids with XPath
$xpath = $doc->xpath("//product/@id");
$xmlids = [];
foreach($xpath as $item => $value){ $xmlids[] = (string)$value; }
// Compare difference with $array
$array = array("1","4","5");
$removeids = array_diff($xmlids, $array);
// Dynamically build XSLT string for each resulting id
foreach($removeids as $id){
$xslstr='<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="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="product[@id=\''.$id.'\']"/>
</xsl:transform>';
$xsl = new SimpleXMLElement($xslstr);
// Configure the transformer and run
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
$newXML = $proc->transformToXML($doc);
// Adjust $doc object with each loop
$doc = new SimpleXMLElement($newXML);
}
// Echo Output
echo $doc->asXML();