XPath filtering on attribute with namespace

18,760

Solution 1

That XPath looks correct.

It could be that your library doesn't support namespaced attributes, or that you haven't properly registered the yt namespace and/or the media namespace.

Try just matching on the local-name() and namespace-uri() inside of predicate filters, rather than using the namespace-prefix:

./*[local-name()='group'
      and namespace-uri()='http://search.yahoo.com/mrss/'
    ]/*[local-name()='thumbnail'
         and namespace-uri()='http://search.yahoo.com/mrss/'
         and @*[local-name()='name'
                 and namespace-uri()='http://gdata.youtube.com/schemas/2007'
                 and .='hqdefault'
                ]
        ]/@url

If this works, then there is an issue registering the namespaces for those namespace-prefixes.

Solution 2

Assuming the rest is in order, simply replace the first . in the xpath with / to get //media:group/... (or begin with /atom:feed/media:group/... and register the atom namespace).

Here's a complete working example:

<?php
$dom = new DOMDocument();
$dom->loadXML( <<<XML
<feed xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/'
  xmlns:yt='http://gdata.youtube.com/schemas/2007'>
  <entry>
    <media:group>
      <media:thumbnail url='http://i.ytimg.com/1.jpg' yt:name='default'/>
      <media:thumbnail url='http://i.ytimg.com/2.jpg' yt:name='hqdefault'/>
      <media:thumbnail url='http://i.ytimg.com/3.jpg' yt:name='start'/>
      <media:thumbnail url='http://i.ytimg.com/4.jpg' yt:name='middle'/>
    </media:group>
  </entry>
</feed>
XML
);

$x = new DOMXPath( $dom );
$x->registerNamespace( 'yt', 'http://gdata.youtube.com/schemas/2007' );
$x->registerNamespace( 'media', 'http://search.yahoo.com/mrss/' );
$l= $x->query( "//media:group/media:thumbnail[@yt:name='hqdefault']/@url" );
for ($i=0; $i<$l->length; $i++) var_dump( $l->item($i)->value );
Share:
18,760
wurdalack
Author by

wurdalack

Updated on June 06, 2022

Comments

  • wurdalack
    wurdalack almost 2 years

    I need to create XPath expression to filter based on attribute that is in given namespace. Example XML is:

    <feed xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/'
      xmlns:yt='http://gdata.youtube.com/schemas/2007'> ...
     <entry>
      <media:group>
       <media:thumbnail url='http://i.ytimg.com/1.jpg' yt:name='default'/>
       <media:thumbnail url='http://i.ytimg.com/2.jpg' yt:name='hqdefault'/>
       <media:thumbnail url='http://i.ytimg.com/3.jpg' yt:name='start'/>
       <media:thumbnail url='http://i.ytimg.com/4.jpg' yt:name='middle'/>
      </media:group>
     </entry>
    

    And I need to get the url of the node with attribute yt:name set to 'hqdefault'.

    I tried with XPath expression

    './media:group/media:thumbnail[@yt:name='hqdefault']/@url'
    

    but it seems that specifying namespaced attribute with yt:name does not work. I get an empty DOMNodeList upon making a query.

    I am accessing XML in php, so I registered yt namespace:

    registerNamespace( 'yt', 'http://gdata.youtube.com/schemas/2007' );
    

    Thnx in advance

  • wurdalack
    wurdalack almost 13 years
    I did not enter the whole XML,sorry. It is YouTube playlist export XML and it starts with: <feed xmlns='http://www.w3.org/2005/Atom' xmlns:media='http://search.yahoo.com/mrss/' xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/' xmlns:gd='http://schemas.google.com/g/2005' xmlns:yt='http://gdata.youtube.com/schemas/2007' gd:etag='W/&quot;C04ESH47eCp7ImA9WhZWGUk.&quot;'> I am accessing XML in php, so I registered yt namespace: registerNamespace( 'yt', 'http://gdata.youtube.com/schemas/2007' ); It does not work in sense that I get an empty DOMNodeList upon making a query. Thnx