5

当我将 libxml 与 XPath 一起使用时,我遇到了问题。我想解析一个 youtube 播放列表:

<?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 表达式“/feed”时,xmlXPathEvalExpression 说我找不到。

如果我删除 feed 的所有 xmlns 属性,它就可以工作。即使使用 xmlns 属性,我怎样才能使它工作?

我将 libxml 与 Objective-C 一起使用

4

5 回答 5

3

I ran into a similar issue when trying to use libxml-ruby to parse through xml. From http://libxml.rubyforge.org/rdoc/classes/LibXML/XML/XPath.html:

To find nodes you must define the atom namespace for libxml. One way to do this is:

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

Alternatively, you can register the default namespace like this:

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

Either way works, but registering makes sense if you're going to be using the methods a lot. Then you can just reference items like 'atom:title'.

于 2011-04-22T21:18:45.367 回答
3

我正在使用XPathQuery包装器,xmlXPathEvalExpression这使得走这xmlXpathRegisterNS条路变得更加困难。

如果您直接查询字段,您可能不关心命名空间 - 这对我的应用程序无关紧要。因此,我只是在处理 XML 之前对其进行了修改。

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

现在你可以使用modifiedXMLDatainxmlXPathEvalExpression或者PerformXMLXPathQuery如果你使用XPathQuery.

于 2011-01-21T04:06:31.000 回答
2

您没有发布查询代码,但听起来您没有使用 XpathContext 注册名称空间。这是xmlXPathRegisterNS的 API 文档,我相信它会满足您的需求。它不允许您注册默认名称空间,因此您需要将 XPath 表达式更改为 /feed:feed 等。

于 2009-08-30T14:57:48.520 回答
2

要使用默认命名空间,只需注册命名空间 xlmns=,然后在查询中使用 /xmlns:feed。

于 2010-10-28T10:27:57.940 回答
1

经过一番研究,我发现以下解决方案就像 NSXMLDocument 路径查询一样工作:

当 xml 文档声明一个没有前缀的默认命名空间时,比如 xmlns="..."

简单的 xpaths 查询失败,例如 xpath: /node

那是因为xmlXPathEvalExpression需要某种默认命名空间前缀,但没有。

一种方法是修复缺少的前缀(就像 GDataXML 一样),但这需要所有 xpath 都使用这个前缀,比如 xpath: /__def_ns:node

但这不是 xpath 的NSXMLDocument工作方式。

以下解决方案(基于 a 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];
}
于 2014-01-29T17:05:39.670 回答