如何用php递归更新xml属性值?

时间:2014-02-19 02:16:17

标签: php xml simplexml

我正在编写一个函数来将所有属性值重置为给定xml文件的空字符串。有人可以帮我修复此功能来执行所请求的任务吗?谢谢!

// reset all attribute values to NULL or ""
function resetAttributes($xml) {
    foreach($xml->children() as $child) {
        foreach($child->attributes() as $attr) {
            $attr = "";
        }
        resetAttributes($child);

    }
    return $xml;
}

$xml = simplexml_load_file($xmlFile);
resetAttributes($xml);
$xml->asXML($xmlFile);

// Michael Berkowski解决方案的修订!!内在孩子的属性保持不变。也许这是因为我的PHP版本?有关详细信息,请参阅底部的屏幕截图。

<?php
header('Content-type: text/plain');
$xmlString = <<<XMLSTR
<?xml version="1.0"?>
<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description attr='12345'>An in-depth look at creating applications 
      with XML.</description>
      <sub attr='99'>
        <subsub attr1='asdb'/>
        <subsub attr1='asdb' attr2='xss'/>
      </sub>
   </book>
   <book id="bk102">
      <author  attr='54321' attr2='99999'>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price price='88888'>5.95</price>
      <publish_date>2000-12-16</publish_date>
      <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.</description>
   </book>
</catalog>
XMLSTR;

$xml = new RecursiveIteratorIterator(new SimpleXMLIterator($xmlString), RecursiveIteratorIterator::SELF_FIRST);
// Then just loop over it. The recursion will be automatic
foreach ($xml as $node) {
  foreach ($node->attributes() as $attr => $value) {
    // Set the attribute to an empty string the same way as in 
    // your recursive function...
    echo (string)$attr;
    $node->attributes()->$attr = '';
  }
}
// That's all, write out the XML.
echo '<pre>' . $xml->asXML() . '</pre>';
  1. http://img42.com/l9tSg
  2. http://img42.com/9b18L

1 个答案:

答案 0 :(得分:4)

你肯定是正确的,你的递归将正常工作,但在迭代属性时,你应该在$attr => $value中使用foreach(),并使用动态属性专门设置属性名称$child->attributes()->$attr。这可能不是使用SimpleXMLElement执行此操作的唯一方法,但它很容易且有效。

function resetAttributes($xml) {
    foreach($xml->children() as $child) {
        foreach($child->attributes() as $attr => $value) {
            // Call attributes() and identify the attribute by name
            // which you get from $attr in the iteration
            $child->attributes()->$attr = "";
        }
        // Recurse as you are doing...
        resetAttributes($child);
    }
    return $xml;
}

$xml = simplexml_load_file($xmlFile);
resetAttributes($xml);
$xml->asXML($xmlFile);

但我们可以使用PHP的SPL迭代器做得更好......

理想情况下,您可以执行此操作using a RecursiveIteratorIterator,因为SimpleXMLIterator实现了RecursiveIterator界面。

// The SimpleXMLIterator constructor wants a string...
$xmlString = file_get_contents($xmlFile);
// Instantiate a new RecursiveIteratorIterator for SimpleXML
$xml = new RecursiveIteratorIterator(new SimpleXMLIterator($xmlString), RecursiveIteratorIterator::SELF_FIRST);
// Then just loop over it. The recursion will be automatic
foreach ($xml as $node) {
  foreach ($node->attributes() as $attr => $value) {
    // Set the attribute to an empty string the same way as in 
    // your recursive function...
    $node->attributes()->$attr = '';
  }
}
// That's all, write out the XML.
$xml->asXML($xmlFile);