2009-08-30 2 views
4

У меня проблема, когда я использую libxml с XPath. Я хочу, чтобы разобрать плейлист YouTube:Проблема с пространством имен и libxml при использовании Xpath

<?xml version='1.0' encoding='UTF-8'?> 
<feed xmlns='http://www.w3.org/2005/Atom' 
    xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/' 
    xmlns:media='http://search.yahoo.com/mrss/' 
    xmlns:batch='http://schemas.google.com/gdata/batch' 
    xmlns:yt='http://gdata.youtube.com/schemas/2007' 
    xmlns:gd='http://schemas.google.com/g/2005' 
    gd:etag='W/&quot;Dk8DRn47eCp7ImA9WxRQGEk.&quot;'> 
    <id>tag:youtube,2008:user:andyland74:playlists</id> 
    <updated>2008-07-21T16:43:25.232Z</updated> 
    <category scheme='http://schemas.google.com/g/2005#kind' 
    term='http://gdata.youtube.com/schemas/2007#playlistLink'/> 
    <title>Playlists of andyland74</title> 
    <logo>http://www.youtube.com/img/pic_youtubelogo_123x63.gif</logo> 
    <link rel='related' type='application/atom+xml' 
    href='http://gdata.youtube.com/feeds/api/users/andyland74?v=2'/> 
    <link rel='alternate' type='text/html' 
    href='http://www.youtube.com/profile_play_list?user=andyland74'/> 
    <link rel='http://schemas.google.com/g/2005#feed' 
    type='application/atom+xml' 
    href='http://gdata.youtube.com/feeds/api/users/andyland74/playlists?v=2'/> 
    <link rel='http://schemas.google.com/g/2005#post' 
    type='application/atom+xml' 
    href='http://gdata.youtube.com/feeds/api/users/andyland74/playlists?v=2'/> 
    <link rel='http://schemas.google.com/g/2005#batch' 
    type='application/atom+xml' 
    href='http://gdata.youtube.com/feeds/api/users/andyland74/playlists/batch?v=2'/> 
    <link rel='self' type='application/atom+xml' 
    href='http://gdata.youtube.com/feeds/api/users/andyland74/playlists?...'/> 
    <link rel='service' type='application/atomsvc+xml' 
    href='http://gdata.youtube.com/feeds/api/users/andyland74/playlists?alt=...'/> 
    <author> 
    <name>andyland74</name> 
    <uri>http://gdata.youtube.com/feeds/api/users/andyland74</uri> 
    </author> 
    <generator version='2.0' 
    uri='http://gdata.youtube.com/'>YouTube data API</generator> 
    <openSearch:totalResults>3</openSearch:totalResults> 
    <openSearch:startIndex>1</openSearch:startIndex> 
    <openSearch:itemsPerPage>25</openSearch:itemsPerPage> 
    <entry gd:etag='W/&quot;Dk8DRn47eCp7ImA9WxRQGEk.&quot;'> 
    <id>tag:youtube,2008:user:andyland74:playlist:8BCDD04DE8F771B2</id> 
    <published>2007-11-04T17:30:27.000-08:00</published> 
    <updated>2008-07-15T12:33:20.000-07:00</updated> 
    <app:edited xmlns:app='http://www.w3.org/2007/app'>2008-07-15T12:33:20.000-07:00</app:edited> 
    <category scheme='http://schemas.google.com/g/2005#kind' 
     term='http://gdata.youtube.com/schemas/2007#playlistLink'/> 
    <title>My New Playlist Title</title> 
    <summary>My new playlist Description</summary> 
    <content type='application/atom+xml;type=feed' 
     src='http://gdata.youtube.com/feeds/api/playlists/8BCDD04DE8F771B2?v=2'/> 
    <link rel='related' type='application/atom+xml' 
     href='http://gdata.youtube.com/feeds/api/users/andyland74?v=2'/> 
    <link rel='alternate' type='text/html' 
     href='http://www.youtube.com/view_play_list?p=8BCDD04DE8F771B2'/> 
    <link rel='self' type='application/atom+xml' 
     href='http://gdata.youtube.com/feeds/api/users/andyland74/playlists/8BCDD04DE8F771B2?v=2'/> 
    <link rel='edit' type='application/atom+xml' 
     href='http://gdata.youtube.com/feeds/api/users/andyland74/playlists/8BCDD04DE8F771B2?v=2'/> 
    <author> 
     <name>andyland74</name> 
     <uri>http://gdata.youtube.com/feeds/api/users/andyland74</uri> 
    </author> 
    <yt:countHint>9</yt:countHint> 
    </entry> 
</feed> 

, когда я использую следующее выражение XPath «/ корма», то xmlXPathEvalExpression сказать мне, что я оленья кожа найти.

если я удалю все атрибуты xmlns, в которых он работает. Как я могу заставить его работать даже с атрибутами xmlns?

я использую LibXML с Objective-C

+0

Один из многих возможных дубликатов этого FAQ: [libxml2 ошибка с пространствами имен и XPath] (http://stackoverflow.com/questions/3135175/libxml2-error-with-namespaces-and-xpath) – 2011-04-22 23:50:07

ответ

1

Вы не отправлял код запроса, но это звучит, как вы не регистрируя пространств имен с вашим XpathContext. Вот документы API для xmlXPathRegisterNS, я считаю, что он будет делать то, что вы ищете. Он не позволит вам зарегистрировать пространство имен по умолчанию, поэтому вам нужно будет изменить выражение XPath в/feed: фид или тому подобное.

+2

нормально для функции xmlXpathRegisterNS. Но почему я не могу зарегистрировать пространство имен по умолчанию? почему я должен использовать/feed: выражение подачи, если я просто хочу получить ? – Sly33

+2

такой же вопрос, почему? –

1

Чтобы использовать пространство имен по умолчанию, просто зарегистрируйте пространство имен xlmns = и затем используйте/xmlns: feed в вашем запросе.

2

Я использую обертку XPathQuery около xmlXPathEvalExpression, что затрудняет путь xmlXpathRegisterNS.

Если вы запрашиваете поля напрямую, вам, вероятно, не нужны пространства имен - это не имеет значения для моего приложения. Итак, я только что изменил XML, прежде чем обрабатывать его.

NSString *xmlString = [[NSString alloc] initWithData:originalXMLData encoding:NSUTF8StringEncoding]; 
NSString *modifiedXMLString = [xmlString stringByReplacingOccurrencesOfString:@"xmlns=" withString:@"foobar="]; 
NSData *modifiedXMLData = [modifiedXMLString dataUsingEncoding:NSUTF8StringEncoding]; 

Теперь вы можете использовать modifiedXMLData в xmlXPathEvalExpression или PerformXMLXPathQuery, если вы используете XPathQuery.

+0

Nice 'n легкий. Благодаря! Примечание. Если вы читаете разные XML-данные, убедитесь, что вы используете более уникальную строку. – mattsven

+0

Не будет работать для нестандартных пространств имен, например 'xmlns: potato'. – mattsven

2

Я столкнулся с аналогичной проблемой при попытке использовать libxml-ruby для анализа через xml. От http://libxml.rubyforge.org/rdoc/classes/LibXML/XML/XPath.html:

Для поиска узлов вы должны определить атом пространство имен для Libxml. Один из способов сделать это:

node = doc.find('atom:title', 'atom:http://www.w3.org/2005/Atom')

В качестве альтернативы, вы можете зарегистрировать пространство имен по умолчанию, как это:

doc.root.namespaces.default_prefix = 'atom' node = doc.find('atom:title')

В любом случае работает, но регистрирующий имеет смысл, если вам «Много способов использовать методы. Затем вы можете просто ссылаться на такие элементы, как «atom: title».

0

После некоторых исследований, я нашел следующее решение, которое просто работает как NSXMLDocument пути запросы:

, когда XML-документы объявить пространство имен по умолчанию без префикса, как xmlns="..."

простых XPaths запросов терпят неудачу, как xpath: /node

Это потому, что xmlXPathEvalExpression ожидает какой-то префикс пространства имен по умолчанию, но его нет.

Один подход заключается в фиксации недостающий префикс (например, GDataXML делает), но это требует, чтобы все XPaths использовать этот префикс, как xpath: /__def_ns:node

Но это не так, как XPath-х и NSXMLDocument работы.

Следующее решение (основанное на DDXMLNode) отправляется на корневой узел и сканирует место для имен без префикса. Затем все узлы ниже пересекаются, и если они принадлежат к этому пространству имен, он удаляется. Это похоже на то, что вначале не было пространства имен.

- (void)fixNameSpace 
{ 
    xmlNodePtr nodePtr = (xmlNodePtr)self->genericPtr; 
    xmlNsPtr ns = nodePtr->nsDef; 
    xmlNsPtr defaultNs = NULL; 
    while(ns != NULL) 
    { 
     if (ns->prefix == NULL) 
     { 
      defaultNs = ns; 
      break; 
     } 
     ns = ns->next; 
    } 
    if (defaultNs) 
     [self resetDefaultNs:defaultNs]; 
} 

- (void)resetDefaultNs:(xmlNsPtr)defaultNs 
{ 
    xmlNodePtr nodePtr = (xmlNodePtr)self->genericPtr; 
    xmlNsPtr ns = nodePtr->ns; 
    if (ns && ns == defaultNs) 
     xmlSetNs(nodePtr, NULL); 

    for (NSXMLNode* child in self.children) 
     [child resetDefaultNs:defaultNs]; 
} 
Смежные вопросы