Фильтрация XPath по атрибуту с пространством имен - PullRequest
11 голосов
/ 04 августа 2011

Мне нужно создать выражение XPath для фильтрации на основе атрибута, который находится в данном пространстве имен.Пример 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>

И мне нужно получить URL узла с атрибутом yt: name, установленным в 'hqdefault'.

Я пытался с XPath выражением

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

но похоже, что указание атрибута namespaced с помощью yt: name не работает.Я получаю пустой DOMNodeList после выполнения запроса.

Я обращаюсь к XML в php, поэтому я зарегистрировал пространство имен yt:

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

Заранее спасибо

Ответы [ 3 ]

5 голосов
/ 07 августа 2011

Этот XPath выглядит правильно.

Возможно, ваша библиотека не поддерживает атрибуты пространства имен или вы неправильно зарегистрировали пространство имен yt и / или пространство имен media.

Попробуйте просто сопоставить local-name() и namespace-uri() внутри фильтров предикатов, а не использовать префикс пространства имен:

./*[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

Если это работает, возникает проблема с регистрацией пространств имен для этих префиксов пространств имен.

1 голос
/ 26 марта 2014

Если все по порядку, просто замените первый . в xpath на /, чтобы получить //media:group/... (или начните с /atom:feed/media:group/... и зарегистрируйте пространство имен атомов).

Вот полный рабочий пример:

<?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 );
0 голосов
/ 04 августа 2011

Префикс пространства имен yt используется в вашем примере XML, но не объявлен. Если этот пример XML действительно есть, это не правильно сформированный XML (в терминах пространства имен). Поэтому никакие универсальные инструменты XML, такие как XSLT, вряд ли смогут его обработать.

С другой стороны, если где-то в исходном документе есть объявление префикса пространства имен yt, которое вы нам не показали, вам нужно объявить в своей среде обработки XPath (я полагаю, XSLT) префикс для тот же URI пространства имен. Э.Г.

<xsl:stylesheet ... xmlns:yt="theNamespaceURIForYT">

XPath не знает ни одного объявления префикса пространства имен, встречающегося в исходном документе. Он знает только, к какому пространству имен (URI) относится каждый элемент (и атрибут).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...