2013-08-08 33 views
6

Aşağıda, bir XML dosyasında arama yapıp <AnotherChild> kimliğini bulmam gereken bir PHP script var. Herhangi bir nedenle, şu anda 0 sonuç döndürüyor ve nedenini anlayamıyorum. Herhangi biri neden 0 döndürdüğünü görebiliyorsa, nedenini bilmeme izin verirse gerçekten çok memnun olurum.PHP XPath arama dönen 0 sonuç

XML:

<TransXChange xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.transxchange.org.uk/" xsi:schemaLocation="http://www.transxchange.org.uk/ http://www.transxchange.org.uk/schema/2.1/TransXChange_general.xsd" CreationDateTime="2013-07-12T18:12:21.8122032+01:00" ModificationDateTime="2013-07-12T18:12:21.8122032+01:00" Modification="new" RevisionNumber="3" FileName="swe_44-611A-1-y10.xml" SchemaVersion="2.1"> 
    <Node1>...</Node1> 
    <Node2>...</Node2> 
    <Node3>...</Node3> 
    <Node4>...</Node4> 
    <Node5>...</Node5> 
    <Node6>...</Node6> 
    <Node7> 
     <Child> 
      <id>ABCDEFG123</id> 
     </Child> 
     <AnotherChild> 
      <id>ABCDEFG124</id> 
     </AnotherChild> 
    </Node7> 
    <Node8>...</Node8> 
</TransXChange> 

PHP:

<?php 

    $xmldoc = new DOMDocument(); 
    $xmldoc->load("directory1/directory2/file.xml"); 

    $xpathvar = new DOMXPath($xmldoc); 
    $xpathvar->registerNamespace('transXchange', 'http://www.transxchange.org.uk/'); 

    $queryResult = $xpathvar->query('//AnotherChild/id'); 
    foreach($queryResult as $result) { 
    echo $result->textContent; 
    } 
?> 

Teşekkür

+0

[ad ile xpath] (http olası yinelenen: // stackoverflow.com/questions/9827685/xpath-with-namespace) – Wrikken

+0

[bununla birlikte daha iyi olabilir] (http://stackoverflow.com/questions/6475394/php-xpath-query-on-xml-with-default- ad alanı-bağlayıcı) – Wrikken

+0

@Wrikken Her iki cevaba da baktım ve sorunumu gidermek için kodumu nasıl ayarlayacağımı göremedim? – jskidd3

cevap

9

Yorumlar ile bağlantılı iki soru aslında bu soruyu yanıtlıyor, ancak neden niçin IMO'yu yanıtlayamadıklarını açıklığa kavuşturamadıklarından, bunu my answer in chat takip edeceğim.

<root> 
    <child> 
    <grandchild>foo</grandchild> 
    </child> 
</root> 

Bu da hiç xmlns özellikleri olan, sen //grandchild sorgulamak ve beklediğiniz sonucu alabilirsiniz anlamı:


aşağıdaki XML belgesi düşünün. Her düğüm varsayılan ad alanı'dadır, bu nedenle her şey, XPath'te bir ad alanı kaydetmeden adreslenebilir.

<root xmlns="http://www.bar.com/"> 
    <child> 
    <grandchild>foo</grandchild> 
    </child> 
</root> 

Bu http://www.bar.com/ bir ad alanı bildiriyor ve bunun bir sonucu olarak üye düğümünü ele almayı ad kullanmanız gerekir:

Şimdi bu düşünün. Zaten anladım gibi

, Bunu yapmanın yolu DOMXPath::registerNamespace() kullanmaktır - ancak cevapsız önemli bir noktadır ki (PHP en XPath uygulaması) her isim bir önek olarak kayıtlı olması gerekir ve kullanmak gerekir Bu önek, ona ait olan düğümleri adreslemek için. Boş bir önek ile XPath'ta bir isim alanını kaydettirmek mümkün değildir.

Yani, yukarıda ikinci örnek verilen, orijinal //grandchild sorguyu yürütmek nasıl bakalım: biz URI var kullanarak ad kayıtlı nasıl

<?php 

    $doc = new DOMDocument(); 
    $doc->loadXML($xml); 

    $xpath = new DOMXPath($doc); 
    $xpath->registerNamespace('bar', 'http://www.bar.com/'); 

    $nodes = $xpath->query('//bar:grandchild'); 
    foreach($nodes as $node) { 
     // do stuff with $node 
    } 

Not ve biz bir önek belirtildi. Özgün XML bu öneki içermese de, example sorgusundaki öneki kullanırız.

neden XML başka parçasına bakıp sağlar anlamak için:

<baz:root xmlns:baz="http://www.bar.com/"> 
    <baz:child> 
    <baz:grandchild>foo</baz:grandchild> 
    </baz:child> 
</baz:root> 

Bu belge ikinciyesemantik aynıdır - kod örneği ya (proof) ile aynı derecede işe yarar. Önek ad alanından ayrıdır. Bu belgede bir baz: öneki kullanıyor olsa da, XPath bar: önekini kullanır. Bunun nedeni, ad alanını tanımlayan düşüncenin, önek olan değil. Bir belge bir ad alanı kullandığında

Demek ki XPath'de ad kaydı ve biz bu ad alanına ait herhangi düğümler başvurmak için karşı kayıtlı öneki kullanılarak, karşı değil, ile ad çalışmalıdır. lütfen ilk belgeye bu ilkeleri uygularken

Bütünlüğü için

, söz konusu kod ile kullanmak istiyorsunuz sorgusu:

//transXchange:AnotherChild/transXchange:id 
+0

Böylesine harika ve ayrıntılı bir cevap verdiğiniz için teşekkürler! – jskidd3

+0

@JoelKidd Sorun yok, sohbet odasında PHP'de XML ve XPath'a oldukça aşina olan bir kaç düzenli var, hakre [bloglar] (http://hakre.wordpress.com/) hakkında Eğer kontrol etmek istiyorsanız periyodik aralıklarla incelemeler :-) – DaveRandom

+0

Bu harika! Okumak, blogu işaretleyeceğim. Tekrar teşekkürler. – jskidd3

2

Ben ilk ad kayıtlı Bu sorunu gidermek için:

$xpathvar->registerNamespace('transXchange', 'http://www.transxchange.org.uk/'); 

Ve sonra benzeri bir sorgu modifiye çok:

$queryResult = $xpathvar->query('//transXchange:AnotherChild/transXchange:id'); 

Bu, kimliği başarıyla döndürdü.