删除XML中的属性

时间:2014-10-30 14:06:19

标签: php xml

我想从每个size="id"元素中完全删除<door>属性。

<?xml version="1.0" encoding="UTF-8"?>
<doors>
<door id="1" entry="3249" size="30"/>
<door id="1041" entry="6523" size="3094"/>
-- and 1000 more....
</doors>

PHP代码:

$xml = new SimpleXMLElement('http://mysite/doors.xml', NULL, TRUE);
$ids_to_delete = array( 1, 1506 );
foreach ($ids_to_delete as $id) {
    $result = $xml->xpath( "//door[@size='$id']" );
    foreach ( $result as $node ) {
        $dom = dom_import_simplexml($node);
        $dom->parentNode->removeChild($dom);
    }
}

$xml->saveXml();

我没有错误,但它没有删除size属性。为什么呢?

2 个答案:

答案 0 :(得分:1)

您可以使用DOMXPath在DOMDocument中完成整个查询,而不是在SimpleXML和DOM之间切换:

$dom = new DOMDocument;
$dom->load('my_xml_file.xml');

# initialise an XPath object to act on the $dom object
$xp = new DOMXPath( $dom );

# run the query
foreach ($xp->query( "//door[@size]" ) as $door) {
    # remove the attribute
    $door->removeAttribute('size');
}

print $dom->saveXML();

您提供的输入的输出:

<?xml version="1.0" encoding="UTF-8"?>
<doors>
    <door id="1" entry="3249"/>
    <door id="1041" entry="6523"/>
</doors>

如果您只想删除列表中ID的size属性,则应使用以下代码:

foreach ($ids_to_delete as $id) {
    # searches for elements with a matching ID and a size attribute
    foreach ($xp->query("//door[@id='$id' and @size]") as $door) {
        $door->removeAttribute('size');
    }
}

您的代码无法正常工作:

  • 看起来你的XPath错了,因为你的数组被调用$ids_to_delete而你的XPATH正在寻找size元素等于$ids_to_delete的值的门元素;

  • 您正在将节点转换为DOMDocument对象($dom = dom_import_simplexml($node);)以进行删除,但我认为您以某种方式打印的$xml->saveXml();是一个SimpleXML对象;

  • 您需要删除元素属性; removeChild删除整个元素。

答案 1 :(得分:0)

  

我没有错误,但它没有删除size属性。为什么呢?

有多种原因导致它不删除size属性。首先出现在我脑海中的是属性不是子节点。使用删除子项的方法不适合删除属性。

  

每个元素节点都有一组关联的属性节点;元素是每个属性节点的父节点;但是,属性节点不是其父元素的子元素

来自: Attribute Nodes - XML Path Language (XPath),由我大胆。

但是,这里没有看到错误,因为您拥有的$result是一个空数组。您只是不选择要使用xpath删除任何要删除的节点(既不是元素也不是属性)。那是因为你找不到这样的元素:

//door[@size='1']

您正在搜索size属性中的id:No match。

这就是为什么你没有错误并且它不删除任何大小属性的原因:1。)你不删除属性,2。)你不查询任何元素来删除属性。

如何删除Xpath查询的SimpleXML中的属性?

您可以通过使用Xpath查询选择它们来删除属性节点,然后取消设置SimpleXMLElement self-reference

// all size attributes of all doors
$result = $xml->xpath("//door/@size");
foreach ($result as $node) {
    unset($node[0]);
}

在此示例中,所有属性节点都由Xpath表达式查询,这些表达式是门元素的大小属性(这是您在问题中要求的),然后从XML中删除它们。

//door/@size

(见Abbreviated Syntax

现在这里有完整的例子:

<?php
/**
 * @link https://eval.in/215817
 */

$buffer = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<doors>
<door id="1" entry="3249" size="30"/>
<door id="1041" entry="6523" size="3094"/>
-- and 1000 more....
</doors>
XML;

$xml = new SimpleXMLElement($buffer);

// all size attributes of all doors
$result = $xml->xpath("//door/@size");
foreach ($result as $node) {
    unset($node[0]);
}

$xml->saveXml("php://output");

输出(Online Demo):

<?xml version="1.0" encoding="UTF-8"?>
<doors>
<door id="1" entry="3249"/>
<door id="1041" entry="6523"/>
-- and 1000 more....
</doors>