dongying7847 2015-03-23 20:01
浏览 75
已采纳

命名空间和XPath

I'm exploring XML and PHP, mostly XPath and other parsers.

Here be the xml:

<?xml version="1.0" encoding="UTF-8"?>

<root xmlns:foo="http://www.foo.org/" xmlns:bar="http://www.bar.org">
    <actors>
        <actor id="1">Christian Bale</actor>
        <actor id="2">Liam Neeson</actor>
        <actor id="3">Michael Caine</actor>
    </actors>
    <foo:singers>
        <foo:singer id="4">Tom Waits</foo:singer>
        <foo:singer id="5">B.B. King</foo:singer>
        <foo:singer id="6">Ray Charles</foo:singer>
    </foo:singers>
    <items>
        <item id="7">Pizza</item>
        <item id="8">Cheese</item>
        <item id="9">Cane</item>
    </items>
</root>

Here be my path & code:

$xml = simplexml_load_file('xpath.xml');

$result = $xml -> xpath('/root/actors');

echo '<pre>'.print_r($result,1).'</pre>';

Now, said path returns:

Array
(
    [0] => SimpleXMLElement Object
        (
            [actor] => Array
                (
                    [0] => Christian Bale
                    [1] => Liam Neeson
                    [2] => Michael Caine
                )
        )
)

Whereas a seemingly similar line of code, which I would have though would result in the singers, doesnt. Meaning:

$result = $xml -> xpath('/root/foo:singers');

Results in:

Array
    (
        [0] => SimpleXMLElement Object
            (
            )

    )

Now I would've thought the foo: namespace in this case is a non-issue and both paths should result in the same sort of array of singers/actors respectively? How come that is not the case?

Thank-you!

Note: As you can probably gather I'm quite new to xml so please be gentle.

Edit: When I go /root/foo:singers/foo:singer I get results, but not before. Also with just /root I only get actors and items as results, foo:singers are completely omitted.

  • 写回答

2条回答 默认 最新

  • dpvp56187 2015-03-23 21:59
    关注

    SimpleXML is, for a number of reasons, simply a bad API.

    For most purposes I suggest PHP's DOM extension. (Or for very large documents a combination of it along with XMLReader.)

    For using namespaces in xpath you'll want to register those you'd like to use, and the prefix you want to use them with, with your xpath processor.


    Example:

    $dom = new DOMDocument();
    $dom->load('xpath.xml');
    $xpath = new DOMXPath($dom);
    
    // The prefix *can* match that used in the document, but it's not necessary.
    $xpath->registerNamespace("ns", "http://www.foo.org/");
    
    foreach ($xpath->query("/root/ns:singers") as $node) {
        echo $dom->saveXML($node);
    }
    

    Output:

    <foo:singers>
        <foo:singer id="4">Tom Waits</foo:singer>
        <foo:singer id="5">B.B. King</foo:singer>
        <foo:singer id="6">Ray Charles</foo:singer>
    </foo:singers>
    

    DOMXPath::query returns a DOMNodeList containing matched nodes. You can work with it essentially the same way you would in any other language with a DOM implementation.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?