duan0531 2013-11-21 10:16
浏览 53
已采纳

XPATH - 当内部节点名称空间不同时,在一个节点下返回整个对象

Another XPath question. I have an API to query which contains multiple nested namespaces.

<feed xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:media="http://search.yahoo.com/mrss/" xmlns="http://www.w3.org/2005/Atom" xmlns:pamedia="http://paimages.co.uk/pamedia.htm">
<title>
    Image / video search results
</title>
<subtitle>
    Images / video found containing the search string provided
</subtitle>
<pamedia:found>
    2228
</pamedia:found>
<pamedia:perpage>
    100
</pamedia:perpage>
<pamedia:page>
    1
</pamedia:page>
<opensearch:totalResults>
    2228
</opensearch:totalResults>
<opensearch:itemsPerpage>
    100
</opensearch:itemsPerpage>
<opensearch:startIndex>
    1
</opensearch:startIndex>
<id>
    http://images.pressassociation.com/cgi/search_api/?state=search&q=miley
</id>
<link rel="self" href="http://images.pressassociation.com/cgi/search_api/?state=search&q=miley"></link>
<link rel="next" href="http://images.pressassociation.com/cgi/search_api/?state=search&q=miley&offset=2"></link>
<link rel="last" href="http://images.pressassociation.com/cgi/search_api/?state=search&q=miley&offset=23"></link>
<updated>
    2013-11-21T09:13:21Z
</updated>
<link rel="self" href="http://images.pressassociation.com/cgi/search_api/?state=search&q=miley">
    <updated>
        2013-11-21T09:13:21Z
    </updated>
    <name>
        Press Association Images
    </name>
    <email>
        redacted
    </email>
</link>
<entry>
    <pamedia:media-type>
        image/jpeg
    </pamedia:media-type>
    <pamedia:event_date>
        2013-11-14
    </pamedia:event_date>
    <pamedia:urn>
        18209006
    </pamedia:urn>
    <pamedia:domain>
        2
    </pamedia:domain>
    <pamedia:domain_prefix>
        PA
    </pamedia:domain_prefix>
    <link type="application/vnd.iptc.g2.newsitem+xml" href="http://images.pressassociation.com/meta/2.18209006.xml"></link>
    <link rel="related" href="http://images.pressassociation.com/meta/2.18209006.html" type="text/html"></link>
    <link rel="related" href="http://images.pressassociation.com/empicsthumbnail/vol183/block3642/18209006.jpg" type="image/jpeg"></link>
    <media:thumbnail width="127" medium="image" height="190" url="http://images.pressassociation.com/empicsthumbnail/vol183/block3642/18209006.jpg" type="image/jpeg"></media:thumbnail>
    <media:content expression="sample" medium="image" width="511" height="767" url="http://images.pressassociation.com/image/preview/2.18209006.jpg" type="image/jpeg"></media:content>
    <media:copyright>
        Associated Press
    </media:copyright>
    <media:content expression="full" medium="photo" width="6041" height="4024" url="http://images.pressassociation.com/image/2.18209006.jpg" type="image/jpeg"></media:content>
    <updated>
        2013-11-15T10:56:44Z
    </updated>
    <summary type="html">
        Fans wait for singer Miley Cyrus before the Bambi 2013 media awards in Berlin, Germany, Thursday, Nov. 14, 2013. (AP Photo/Gero Breloer)
    </summary>
    <rights type="html">
        UK picture buyers only BRO110
    </rights>
    <id>
        http://images.pressassociation.com/meta/2.18209006.xml
    </id>
    <title type="html">
        2013 Bambi Media Awards - Berlin
    </title>
    <category term="E"></category>
    <author>
        <name>
            Gero Breloer/AP
        </name>
    </author>
</entry>
<entry>
    <pamedia:media-type>
        image/jpeg
    </pamedia:media-type>
    <pamedia:event_date>
        2013-11-14
    </pamedia:event_date>
    <pamedia:urn>
        18207923
    </pamedia:urn>
    <pamedia:domain>
        2
    </pamedia:domain>
    <pamedia:domain_prefix>
        PA
    </pamedia:domain_prefix>
    <link type="application/vnd.iptc.g2.newsitem+xml" href="http://images.pressassociation.com/meta/2.18207923.xml"></link>
    <link rel="related" href="http://images.pressassociation.com/meta/2.18207923.html" type="text/html"></link>
    <link rel="related" href="http://images.pressassociation.com/empicsthumbnail/vol183/block3642/18207923.jpg" type="image/jpeg"></link>
    <media:thumbnail width="127" medium="image" height="198" url="http://images.pressassociation.com/empicsthumbnail/vol183/block3642/18207923.jpg" type="image/jpeg"></media:thumbnail>
    <media:content expression="sample" medium="image" width="511" height="796" url="http://images.pressassociation.com/image/preview/2.18207923.jpg" type="image/jpeg"></media:content>
    <media:copyright>
        Associated Press
    </media:copyright>
    <media:content expression="full" medium="photo" width="2801" height="1796" url="http://images.pressassociation.com/image/2.18207923.jpg" type="image/jpeg"></media:content>
    <updated>
        2013-11-15T10:56:44Z
    </updated>
    <summary type="html">
        Singer Miley Cyrus arrives for the Bambi 2013 media awards in Berlin, Germany, Thursday, Nov. 14, 2013. (AP Photo/Gero Breloer)
    </summary>
    <rights type="html">
        UK picture buyers only BRO105
    </rights>
    <id>
        http://images.pressassociation.com/meta/2.18207923.xml
    </id>
    <title type="html">
        2013 Bambi Media Awards - Berlin
    </title>
    <category term="E"></category>
    <author>
        <name>
            Gero Breloer/AP
        </name>
    </author>
</entry>

In order to get the media: namespace nodes and the rest of the entry nodes I am using this query: '/namespace:feed/namespace:entry | namespace:entry/media:*' However doing this returns the media nodes as seperate array items:

   rray
(
    [0] => SimpleXMLElement Object
        (
            [link] => Array
                (
                    [0] => SimpleXMLElement Object
                        (
                            [@attributes] => Array
                                (
                                    [href] => http://images.pressassociation.com/meta/2.18209006.xml
                                    [type] => application/vnd.iptc.g2.newsitem+xml
                                )

                        )

                    [1] => SimpleXMLElement Object
                        (


 [@attributes] => Array
                            (
                                [href] => http://images.pressassociation.com/meta/2.18209006.html
                                [rel] => related
                                [type] => text/html
                            )

                    )

                [2] => SimpleXMLElement Object
                    (
                        [@attributes] => Array
                            (
                                [href] => http://images.pressassociation.com/empicsthumbnail/vol183/block3642/18209006.jpg
                                [rel] => related
                                [type] => image/jpeg
                            )

                    )

            )

        [updated] => 2013-11-15T10:56:44Z
        [summary] => Fans wait for singer Miley Cyrus before the Bambi 2013 media awards in Berlin, Germany, Thursday, Nov. 14, 2013. (AP Photo/Gero Breloer)
        [rights] => UK picture buyers only BRO110
        [id] => http://images.pressassociation.com/meta/2.18209006.xml
        [title] => 2013 Bambi Media Awards - Berlin
        [category] => SimpleXMLElement Object
            (
                [@attributes] => Array
                    (
                        [term] => E
                    )

            )

        [author] => SimpleXMLElement Object
            (
                [name] => Gero Breloer/AP
            )

    )

[1] => SimpleXMLElement Object
    (
        [@attributes] => Array
            (
                [url] => http://images.pressassociation.com/empicsthumbnail/vol183/block3642/18209006.jpg
                [medium] => image
                [type] => image/jpeg
                [width] => 127
                [height] => 190
            )

    )

[2] => SimpleXMLElement Object
    (
        [@attributes] => Array
            (
                [url] => http://images.pressassociation.com/image/preview/2.18209006.jpg
                [medium] => image
                [type] => image/jpeg
                [expression] => sample
                [width] => 511
                [height] => 767
            )

    )

[3] => SimpleXMLElement Object
    (
    )

[4] => SimpleXMLElement Object
    (
        [@attributes] => Array
            (
                [url] => http://images.pressassociation.com/image/2.18209006.jpg
                [medium] => photo
                [type] => image/jpeg
                [expression] => full
                [width] => 6041
                [height] => 4024
            )

    )

I however require [1] [2] [3] & [4] to be nested withing the entry node [0] for extracting values. If anyone could help with this issue I would be very grateful. If possible I would like to be able to return it all with one XPath call.

  • 写回答

1条回答 默认 最新

  • dongshuo9350 2013-11-21 11:21
    关注

    To get entry nodes use only the first part of your expression:

    /atom:feed/atom:entry
    

    To get all entry nodes that have a media descendant node, you could use this expression:

    /atom:feed/atom:entry[.//media:*]
    

    After you get the entry nodes, you wanted use another expression and provide the context in the second argument of query()/evaluate().

    .//media:*
    

    Be aware that you have to register and use your own namespaces prefixes on the SimpleXml/DOMXpath instance.

    I suggest using DOMXpath::evaluate() and not SimpleXmlElement::xpath(). Unlike xpath(), evaluate can return scalar values directly. Expressions like string(.//media:copyright) only work with evaluate(), not with xpath() or DOMXpath::query().

    Here is a small example using DOM+Xpath to query an Atom feed with MediaRss:

    $dom = new DOMDocument();
    $dom->load('feed.xml');
    $xpath = new DOMXpath($dom);
    
    $xpath->registerNamespace('atom', 'http://www.w3.org/2005/Atom');
    $xpath->registerNamespace('media', 'http://search.yahoo.com/mrss/');
    
    foreach ($xpath->evaluate('/atom:feed/atom:entry[.//media:thumbnail]', NULL, FALSE) as $entry) {
      $href = $xpath->evaluate('string(atom:link[@rel = "related" and @type="text/html"]/@href)', $entry, FALSE);
      $src = $xpath->evaluate('string(.//media:thumbnail/@url)', $entry, FALSE);
      printf('<a href="%s"><img src="%s"/></a>', $href, $src);
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥500 火焰左右视图、视差(基于双目相机)
  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本