PHP 解析带和不带命名空间的 XML 文件 [英] PHP parsing XML file with and without namespaces

查看:36
本文介绍了PHP 解析带和不带命名空间的 XML 文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将 XML 文件放入数据库.那不是问题.无法读取它,解析它并创建一些对象以映射到数据库.问题是,有时 XML 文件可以包含命名空间,有时则不能.此外,有时根本没有定义命名空间.

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>

和解析:

$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;
        }
    }

只要没有命名空间就可以了.这是带有命名空间的 XML 文件:

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.

推荐答案

You can make 'http://www.w3schools.com/test/'默认命名空间.这样 a:objects 就会匹配,而不管文档是否说 <a:objects>或<对象>.

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;
}

这篇关于PHP 解析带和不带命名空间的 XML 文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆