Ve ad alanları olmadan PHP ayrıştırma XML dosyası

2 Cevap php

Ben bir veritabanı içine XML dosyasını almak gerekiyor. Sorun değil bu. Cant, okumak bunu ayrıştırmak ve DB eşleştirmek için bazı nesneleri oluşturabilirsiniz. Sorun bazen XML Dosya ad içerir ve bazen olamaz olmasıdır. Furtermore bazen hiç tanımlanmış hiçbir ad yoktur.

Peki ben ilk aldım böyle bir şey oldu:

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

Ve ayrıştırma:

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

Sürece hiçbir ad alanları olduğu gibi Thats ince. Burada ad alanları ile XML Dosyası geliyor:

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

Ben şimdi böyle bir şey geldi:

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

Bu ad alanları ile ve olmadan çalışır. Ama daha iyi bir yolu olması gerektiğini hissediyorum. Bundan önce ben böyle bir şey yapabilirsiniz:

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

Ama bu sadece alışkanlık ad alanları ile çalışır.

2 Cevap

Sen http://www.w3schools.com/test/ 'varsayılan ad yapabilir. Bu şekilde a:objects belge diyor olsun ne olursa olsun maç olur veya .

Bellek kullanımı bir sorun değilse bile bir metin yerine, örneğin ile yapabilirsiniz

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

Sen * herhangi bir öğe eşleşen ve element adına maç olacak, hangi local-name() üzerine maç bir yüklem filtre kullanarak XPATH ifadeleri daha genel yapabilirsiniz ile / ad alanları olmadan.

Böyle bir XPATH:

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

Eğer kullandığınız kod örnek uygulanır:

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