4

私はいくつかのxmlを解析する必要があるiPhoneプロジェクトに取り組んでいます。xml には、デフォルトの名前空間が含まれる場合と含まれない場合があります。デフォルトの名前空間を使用する場合に備えて、xml を解析する方法を知る必要があります。書き込み xml を読み取る必要があるため、KissXML の使用に傾いていますが、提案は受け付けています。

これは私のコードです:

NSString *content = [NSString stringWithContentsOfFile:[[NSBundle mainBundle]
    pathForResource:@"bookstore" ofType:@"xml"] encoding:NSUTF8StringEncoding error:nil];

DDXMLDocument *theDocument = [[DDXMLDocument alloc] initWithXMLString:content options:0 error:nil];

NSArray *results = [theDocument nodesForXPath:@"//book" error:nil];
NSLog(@"%d", [results count]);

この xml で期待どおりに動作します。

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book category="COOKING">
  <title lang="en">Everyday Italian</title>
</book>
<book category="CHILDREN">
  <title lang="en">Harry Potter</title>
</book>
</bookstore>

しかし、xml に名前空間がある場合、次のように動作しなくなります。

<?xml version="1.0" encoding="UTF-8"?>
<bookstore xmlns="[INSERT RANDOM NAMESPACE]">
<book category="COOKING">
  <title lang="en">Everyday Italian</title>
</book>
<book category="CHILDREN">
  <title lang="en">Harry Potter</title>
</book>
</bookstore>

もちろん、文字列を前処理して xmlns を削除することもできますが、それは一種の醜いハックのように感じます。これを処理する適切な方法は何ですか?

4

2 に答える 2

7

クリーンな方法: 名前空間のクエリ

2 つの XPath クエリを使用できます。1 つは名前空間を取得して登録します。2 番目のクエリとして、名前空間を含む既に持っているものを使用します。私はクエリについてしかお手伝いできませんが、名前空間と、それらを KissXML フレームワークに登録する方法に精通しているようです。

namespace-uri(/*)

この式は、XML 定義では単一のルート要素であるドキュメント ルートから始まるすべての子ノードをフェッチし、その名前空間 uri を返します。

醜い方法: ローカル名のテストのみ

KissXML は XPath 1.0 のみをサポートしているようです。この機能の少ない言語バージョンでは、各軸ステップでワイルドカード セレクターを使用し、述語内のローカル名 (名前空間プレフィックスなし) を比較する必要があります。

//*[local-name(.) = 'book']

XPath 2.0 以降では、名前空間のワイルドカードを使用してクエリを実行できます。これははるかに短いものです。

//*:book
于 2013-06-27T08:58:36.340 に答える
5

このコメントによると、 KissXML は「正しい」動作を実装していますが、NSXML はそうではありません。これは正確には役に立ちません。マージされるのを待っているこの修正案があります。[編集] 2021 年 11 月 -まだマージ待ち!

受け入れられた回答の最初に提案された解決策を拡張して、私が見つけた回避策は、デフォルトの名前空間の名前を変更し、そのプレフィックスを XPath クエリで使用することでした。何かのようなもの:

    DDXMLNode *defaultNamespace = [document.rootElement namespaceForPrefix:@""];
    defaultNamespace.name = @"default";
    NSArray *xmlNodes = [[document rootElement] nodesForXPath:@"//default:foo/default:bar" error:nil];

これは、ファイルのテキスト処理よりもきれいに思えます。もちろん、名前空間の競合をチェックして処理することもできますが、上記はほとんどの単純なケースで機能するはずです。

于 2013-12-18T12:10:53.363 に答える