PHP parsing XML file with and without namespaces

怎甘沉沦 提交于 2019-12-11 19:44:18

问题


I need to get a XML File into a Database. Thats not the problem. Cant read it, parse it and create some Objects to map to the DB. Problem is, that sometimes the XML File can contain namespaces and sometimes not. Furtermore sometimes there is no namespace defined at all.

So what i first got was something like this:

<?xml version="1.0" encoding="UTF-8"?>
<struct xmlns:b="http://www.w3schools.com/test/">
<objects>
<object>
<node_1>value1</node_1>
<node_2>value2</node_2>
<node_3 iso_land="AFG"/>
<coords lat="12.00" long="13.00"/>
</object>
</objects>
</struct>

And the parsing:

$obj = new stdClass();
$nodes = array('node_1', 'node_2');

$t = $xml->xpath('/objects/object');    
    foreach($nodes AS $node) {  
        if($t[0]->$node) {
            $obj->$node = (string) $t[0]->$node;
        }
    }

Thats fine as long as there are no namespaces. Here comes the XML File with namespaces:

<?xml version="1.0" encoding="UTF-8"?>
<b:struct xmlns:b="http://www.w3schools.com/test/">
<b:objects>
<b:object>
<b:node_1>value1</b:node_1>
<b:node_2>value2</b:node_2>
<b:node_3 iso_land="AFG"/>
<b:coords lat="12.00" long="13.00"/>
</b:object>
</b:objects>
</b:struct>

I now came up with something like this:

$xml = simplexml_load_file("test.xml");
$namespaces = $xml->getNamespaces(TRUE); 
$ns = count($namespaces) ? 'a:' : ''; 
$xml->registerXPathNamespace("a", "http://www.w3schools.com/test/");

$nodes = array('node_1', 'node_2');

$obj = new stdClass();

foreach($nodes AS $node) {
    $t = $xml->xpath('/'.$ns.'objects/'.$ns.'object/'.$ns.$node);   
    if($t[0]) {
        $obj->$node = (string) $t[0];
    }
}

$t = $xml->xpath('/'.$ns.'objects/'.$ns.'object/'.$ns.'node_3');
if($t[0]) {
    $obj->iso_land = (string) $t[0]->attributes()->iso_land;
}    

$t = $xml->xpath('/'.$ns.'objects/'.$ns.'object/'.$ns.'coords');
if($t[0]) {
    $obj->lat = (string) $t[0]->attributes()->lat;
    $obj->long = (string) $t[0]->attributes()->long;
}

That works with namespaces and without. But i feel that there must be a better way. Before that i could do something like this:

$t = $xml->xpath('/'.$ns.'objects/'.$ns.'object');  
foreach($nodes AS $node) {  
    if($t[0]->$node) {
        $obj->$node = (string) $t[0]->$node;
    }
}

But that just wont work with namespaces.


回答1:


You could make 'http://www.w3schools.com/test/' the default namespace. This way a:objectswould match regardless of whether the document says <a:objects> or <objects>.

If memory usage is not a issue you can even do it with a textual replacement, e.g.

$data = '<?xml version="1.0" encoding="UTF-8"?>
<struct xmlns:b="http://www.w3schools.com/test/">
  <objects>
    <object>
      <node_1>value1</node_1>
      <node_2>value2</node_2>
      <node_3 iso_land="AFG"/>
      <coords lat="12.00" long="13.00"/>
    </object>
  </objects>
</struct>';

$data = str_replace( // or preg_replace(,,,1) if you want to limit it to only one replacement
  'xmlns:b="http://www.w3schools.com/test/"',
  'xmlns="http://www.w3schools.com/test/" xmlns:b="http://www.w3schools.com/test/"',
  $data
);
$xml = new SimpleXMLElement($data);
$xml->registerXPathNamespace("a", "http://www.w3schools.com/test/");

foreach($xml->xpath('//a:objects/a:object') as $n) {
  echo $n->node_1;
}



回答2:


You can make your XPATH statements more generic by matching on any element * and using a predicate filter to match on the local-name(), which will match on the element name with/without namespaces.

An XPATH like this:

/*[local-name()='struct']/*[local-name()='objects']/*[local-name()='object']/*[local-name()='coords']

Applied to the code sample you were using:

$obj = new stdClass();
$nodes = array('node_1', 'node_2');

$t = $xml->xpath('/*[local-name()="objects"]/*[local-name()="object"]');    
    foreach($nodes AS $node) {  
        if($t[0]->$node) {
            $obj->$node = (string) $t[0]->$node;
        }
    }



回答3:


Take a look at This http://blog.sherifmansour.com/?p=302 It helped me a lot.



来源:https://stackoverflow.com/questions/2483887/php-parsing-xml-file-with-and-without-namespaces

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!