77942
お世話になります．  
普段XSLTばかりで、JavaでXPathとかやったことがほとんどないので勝手がわかりません．具体的にはある要素に`@xml:base`属性があるのですが、その値をXPathで拾えないのです．（といいますか属性をXPathで拾えません．）ここを教えていただきたくお願いします．

## 前提要件

以下のような部分を持つXMLファイルをDOMで読み込んでいます．丁度`<plugin>`の要素に位置付けているとお考えください．

```

    <plugin id="org.dita.pdf2" version="3.6.1" xml:base="../plugins/org.dita.pdf2/plugin.xml">
      <!-- extension points -->
      <extension-point id="dita.xsl.xslfo" name="PDF XSLT import"/>
      <extension-point id="dita.xsl.xslfo.i18n-postprocess" name="PDF I18N postprocess import"/>
      <extension-point id="org.dita.pdf2.xsl.topicmerge" name="PDF2 topic merge XSLT import"/>
      <extension-point id="depend.org.dita.pdf2.init.pre" name="Initialization pre-target"/>
      <extension-point id="depend.org.dita.pdf2.format.pre" name="Formatting pre-target"/>
      <extension-point id="depend.org.dita.pdf2.format" name="Formatting target"/>
      <extension-point id="depend.org.dita.pdf2.format.post" name="Formatting post-target"/>
      <extension-point id="depend.org.dita.pdf2.index" name="Indexing target"/>
      <extension-point id="org.dita.pdf2.catalog.relative" name="Configuration XML catalog"/>
      <extension-point id="dita.conductor.pdf2.param" name="PDF XSLT parameters"/>
      <extension-point id="dita.conductor.pdf2.formatter.check" name="Formatter check"/>
      <!-- extensions -->
      <feature extension="dita.conductor.lib.import" file="lib/fo.jar"/>
      <transtype desc="PDF" name="pdf">
        <param desc="Specifies the base file name of the generated PDF file." name="outputFile.base"/>
        ...
      </transtype>
      <transtype desc="PDF2" extends="pdf" name="pdf2"/>
      <feature extension="dita.transtype.print" value="pdf"/>
      ...
    </plugin>
    
```

## やっている処理

次のようにXPathを生成しています．

```

    XPath xpath = XPathFactory.newInstance().newXPath();
    xpath.setNamespaceContext(new NamespaceContext() {
        public String getNamespaceURI(String prefix) {
            return prefix.equals("xml") ? XMLConstants.XML_NS_URI : XMLConstants.NULL_NS_URI;
        }
        public Iterator<?> getPrefixes(String val) {
            return null;
        }
        public String getPrefix(String uri) {
            return null;
        }
    });
    
```

で、以下のコードで`@xml:base`を拾おうとしています．コンテキストのpluginElemは、前提条件で書いたところの`<plugin>`の要素です．（この前提が崩れちゃうと動かなくて当然なんですが、pluginElemは正しく位置付けられています）

```

    // Get plug-in location
    String XPathGetPluginBase = "@xml:base";
    expr = xpath.compile(XPathGetPluginBase);
    Attr pluginBaseAttr = (Attr)expr.evaluate(pluginElem, XPathConstants.NODE);
    String pluginBase = pluginBaseAttr.getValue();
    
```

結果は`pluginBaseAttr`がnullで、pluginBaseAttr.getValue()でNPEでこけちゃいます．

わかる方おられましたらアドバイスをお願いいたします．

以上

## 追記

今XPathを書き換えてみたら

```

    String XPathGetPluginBase = "@*[local-name()='base' and namespace-uri()='http://www.w3.org/XML/1998/namespace']";
    
```

は従来通りNPEで

```

    String XPathGetPluginBase = "@*[local-name()='base']";
    
```

はなんと通ってしまいました．

```

    String pluginBase = pluginBaseAttr.getValue();
    
```

は`../plugins/org.dita.pdf2/plugin.xml`の値になっています．でもこれって本来邪道ですよね（??）
CC BY-SA 4.0
2021-07-02T14:53:30.633
77926
2021-07-03T14:30:39.443
2021-07-02T15:06:10.513
9503
9503
question
java xml xpath
XPathで@xml:baseの値が拾えないです．
すみません．自己解決しました．

もっと上位の問題．元々のDOMを作るときにnamespace-awareにしていませんでした．以下で解決しました．

```

    FileInputStream is = new FileInputStream(Paths.get(pluginsXmlPath).toFile());
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true);
    DocumentBuilder builder = factory.newDocumentBuilder();
    document = builder.parse(is);
    
```

`@xml:base`の取得もわざわざXPath使うまでもありません．

```

    String pluginBase = pluginElem.getAttributeNS(XMLConstants.XML_NS_URI, "base");
    
```

DOMを作ってゴリゴリやるなんて何年ぶりなのですっかり忘れておりました．

大変失礼いたしました．
CC BY-SA 4.0
2021-07-03T14:30:39.443
77942
2021-07-03T14:30:39.443
9503
77926
answer