2009-08-30 62 views
4

我在使用libxml和XPath時遇到了問題。我想分析的YouTube播放清單:當我使用Xpath時,命名空間和libxml出現問題

<?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客觀-C

+0

一個從這個常見問題的許多可能重複:[名稱空間和XPath libxml2的錯誤(http://stackoverflow.com/questions/3135175/libxml2-error-with-namespaces-and-xpath) – 2011-04-22 23:50:07

回答

1

你不發表您的查詢代碼,但它聽起來像是你不註冊你的XpathContext的命名空間。這裏是​​的API文檔,我相信它會做你想要的。它不會讓你註冊一個默認名稱空間,所以你需要將你的XPath表達式改爲/ feed:feed或類似的。

+2

確定爲xmlXpathRegisterNS函數。但爲什麼我不能註冊默認名稱空間?爲什麼我應該使用/ feed:feed表達式,如果我只想得到? – Sly33 2009-08-31 18:48:21

+2

同樣的問題,爲什麼? – 2012-05-24 05:35:49

1

要使用默認名稱空間只需註冊命名空間xlmns =,然後在查詢中使用/ xmlns:feed。

2

我正在使用圍繞xmlXPathEvalExpressionXPathQuery包裝,這使得難以走0123HA路線。

如果您直接查詢字段,則可能不關心名稱空間 - 對我的應用程序無關緊要。所以,我在處理它之前只是修改了XML。現在

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

,你可以,如果你使用XPathQueryxmlXPathEvalExpressionPerformXMLXPathQuery使用modifiedXMLData

+0

好容易。謝謝!注意:如果您正在閱讀各種XML數據,請確保使用更獨特的字符串。 – mattsven 2013-11-16 21:43:18

+0

不適用於非默認名稱空間,如'xmlns:potato'。 – mattsven 2015-11-29 05:18:29

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="..."

簡單的XPath查詢失敗,像 xpath: /node

這是因爲xmlXPathEvalExpression需要某種默認命名空間前綴,但沒有。

一種方法是修復缺少的前綴(如GDataXML做),但要求所有的XPath使用這個前綴,像 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]; 
}