4

ルート ノード用に宣言されたデフォルトの名前空間を持つ XML ファイルで XPath を使用しようとしています。

コード例:

    final SAXBuilder builder = new SAXBuilder();
    final Document document = builder.build(originalFile);

    final XPathFactory xFactory = XPathFactory.instance();

    final String expression = String.format("//section[@label='%s']/section/section", LABEL);
    final XPathExpression<Element> sectionExpression = xFactory.compile(expression, Filters.element());
    final List<Element> sections = sectionExpression.evaluate(document);

セクションが空です。

XML のスニペット

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://www.stellent.com/sitestudio/Project/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.stellent.com/sitestudio/Project/ http://www.stellent.com/sitestudio/ss_project_schema.xsd">
    <section label="Index">
        <section label="xyz">
           <section label="child">
           ...
           </section>
        </section>
    </section>
</project>

作品を削除しxmlns="http://www.stellent.com/sitestudio/Project/"ますが、解決策ではありません!

XPath がこの既定の名前空間を認識できないのはなぜですか? また、なぜ気にするのですか?

さらに良いことに、これを一般的に修正するにはどうすればよいですか?

洞察をありがとう。

4

1 に答える 1

9

JDOM は正しいことをしています。これは、JDOM だけでなく XPath 全般に関する FAQ です。XPath 仕様は、これについて (ある程度) 明確です (関連する部分を太字にしました)

ノード テストの QName は、式コンテキストからの名前空間宣言を使用して展開名に展開されます。これは、 xmlns で宣言されたデフォルトの名前空間が使用されないことを除いて、開始タグと終了タグの要素タイプ名に対して展開が行われるのと同じ方法です。QNameにプレフィックスがない場合、名前空間 URI は null です (これは同じです)。属性名が展開される方法)。QName にプレフィックスがあり、式のコンテキストに名前空間宣言がない場合はエラーです。

XPath の観点からは、これが意味することは、XPath 式のルールのネームスペース処理は、実際には XML のノードと同じではないということです。すべての XPath 式について、式の名前空間コンテキストを定義 (複製) する必要があり、式に使用する接頭辞は、実際の XML ドキュメントで使用されている接頭辞とは完全に独立しています。

デフォルトの名前空間の名前空間プレフィックスを「作成」し、そのプレフィックスを式で使用する必要があります (ここでは、名前空間プレフィックスを作成しましたns)。

final String expression = String.format("//ns:section[@label='%s']/ns:section/ns:section", LABEL);
final XPathExpression<Element> sectionExpression = xFactory.compile(expression, Filters.e, null,
         Namespace.getNamespace("ns", "http://www.stellent.com/sitestudio/Project/"))
于 2014-07-04T12:22:57.957 に答える