5

XPath で libxml を使用しているときに問題が発生しました。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 で見つからないと表示されます。

フィードのすべての xmlns 属性を削除すると機能します。xmlns 属性でも機能させるにはどうすればよいですか?

私はobjective-Cでlibxmlを使用しています

4

5 に答える 5

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];

これmodifiedXMLDataで、xmlXPathEvalExpressionまたはPerformXMLXPathQueryを使用する場合に使用できますXPathQuery

于 2011-01-21T04:06:31.000 に答える
3

libxml-ruby を使用して xml を解析しようとすると、同様の問題に遭遇しました。http://libxml.rubyforge.org/rdoc/classes/LibXML/XML/XPath.htmlから:

ノードを見つけるには、libxml のアトム名前空間を定義する必要があります。これを行う1つの方法は次のとおりです。

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」のようなアイテムを参照するだけです。

于 2011-04-22T21:18:45.367 に答える
2

デフォルトの名前空間を使用するには、名前空間 xlmns= を登録してから、クエリで /xmlns:feed を使用します。

于 2010-10-28T10:27:57.940 に答える
2

クエリ コードを投稿していませんが、名前空間を XpathContext に登録していないようです。ここにxmlXPathRegisterNSの API ドキュメントがあります。探していることを実行できると思います。デフォルトの名前空間を登録できないため、XPath 式を /feed:feed などに変更する必要があります。

于 2009-08-30T14:57:48.520 に答える
1

いくつかの調査の後、NSXMLDocument パス クエリのように機能する次のソリューションを見つけました。

xml ドキュメントが接頭辞なしでデフォルトの名前空間を宣言するとき、 xmlns="..."

次のような単純な xpaths クエリが失敗する xpath: /node

これxmlXPathEvalExpressionは、ある種のデフォルトの名前空間プレフィックスが必要ですが、何もないためです。

1 つのアプローチは、不足しているプレフィックスを修正することです (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];
}
于 2014-01-29T17:05:39.670 に答える