【问题标题】:PHP parsing XML file with and without namespacesPHP 解析带和不带命名空间的 XML 文件
【发布时间】:2010-03-20 16:57:18
【问题描述】:

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

所以我第一次得到的是这样的:

<?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 文件:

<?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>

我现在想出了这样的事情:

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

这适用于命名空间和没有命名空间。但我觉得必须有更好的方法。在此之前我可以做这样的事情:

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

但这不适用于命名空间。

【问题讨论】:

    标签: php xml parsing xpath simplexml


    【解决方案1】:

    您可以将“http://www.w3schools.com/test/”设为默认命名空间。这种方式 a:objects 将匹配,无论文档是 还是

    如果内存使用不是问题,您甚至可以通过文本替换来做到这一点,例如

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

    【讨论】:

    • 我很想这样做,但它不起作用。 $sxe = simplexml_import_dom($doc->importNode($this->reader->expand(), true)); $sxe->registerXPathNamespace('a', "w3schools.com/test"); foreach($sxe->xpath('a:object') as $n) { print_r($n->node_1); }
    【解决方案2】:

    您可以通过匹配任何元素 * 并使用谓词过滤器匹配 local-name() 来使您的 XPATH 语句更通用,这将匹配带有/不带有命名空间的元素名称.

    这样的 XPATH:

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

    应用于您正在使用的代码示例:

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

    【讨论】:

    • 这不起作用:$t = $xml->xpath('/*[local-name()="objects"]/*[local-name()="object"]') ;这有效: $t = $xml->xpath('/*[local-name()="objects"]/*[local-name()="object"]/*');但后来我无法访问密钥...
    【解决方案3】:

    看看这个 http://blog.sherifmansour.com/?p=302 这对我帮助很大。

    【讨论】:

    • RIP 链接。链接已失效。
    猜你喜欢
    • 1970-01-01
    • 2014-07-28
    • 2014-01-30
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    • 2012-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多