PHP:按属性从xml中删除节点

Posted

技术标签:

【中文标题】PHP:按属性从xml中删除节点【英文标题】:PHP: remove node from xml by attribute 【发布时间】:2016-11-13 15:49:56 【问题描述】:

假设我有一个这样的 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(); ?>

非常感谢大家。

【问题讨论】:

【参考方案1】:

考虑部分 XPath 和 XSLT 解决方案,它们都是 Extensible Stylesheet Family 中的兄弟姐妹。 XPath 首先用于检索所有当前的产品 id,然后将其与当前的 id 数组进行比较以继续使用array_diff。然后迭代构建 XSLT 以根据这些不匹配的 id 删除节点。在 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();   

【讨论】:

我没有那个扩展(XSLTProcessor) 您可以在 .ini 文件中启用extension。

以上是关于PHP:按属性从xml中删除节点的主要内容,如果未能解决你的问题,请参考以下文章

使用正则表达式从字符串中删除属性值不是特定值的所有 xml 节点

一次删除属性和匹配的节点

在 Powershell 中从非常大的 XML 文件中删除节点

如何在 PHP 中删除 XML 的节点 [重复]

xml查找节点父节点并删除simplexml php

详解SimpleXML添加_修改_删除_遍历XML节点属性