問題は XPath と名前空間にあります。
あなたのnfeProc
要素は URI の名前空間にありますhttp://www.portalfiscal.inf.br/nfe
。ただし、 の名前空間に接頭辞をバインドしないため、デフォルトの名前空間で名前がxPath
付けられた要素が検索されます。nfeProc
そのような要素は存在しないため、何も返されません。
必要なことは、XPath オブジェクトと XML の名前空間にプレフィックスをバインドすることです。Java では、これはNamespaceContextオブジェクトを使用して行われます。ただし、厄介なことに、NamespaceContext はインターフェースであり、その実装を把握するのは必ずしも容易ではありません。
さらに、XPath ではnfeProc
、例のようにプレフィックスのない名前は常にデフォルトの名前空間 (つまり、名前空間 URI が空の名前) にあることに注意してください。既定の名前空間プレフィックスを他の URI に再バインドすることはできないため、代わりに別のプレフィックス (たとえば、 ) を選択し、nfe
このプレフィックスを XPath で使用する必要があります。これには問題はありません。abc
とxyz
が両方とも同じ名前空間 URI にバインドされている場合、abc:someElement
とxyz:someElement
は同じ名前です。
@MostyMostacho は、XPath 式が正しくないことを正しく指摘しています。評価すると、属性を持つ要素//nfe:nfeProc[@versao]
のテキスト コンテンツが返されますが、この属性の値が必要です。したがって、必要な XPath 式は です。(属性は親要素から名前空間を継承しないため、属性の名前はデフォルトの名前空間のままであることに注意してください。)nfe:nfeProc
versao
//nfe:nfeProc/@versao
versao
カスタム NamespaceContext 実装を使用してすべてをまとめると、次のようになります。
import java.io.StringReader;
import java.util.Collections;
import java.util.Iterator;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.xml.sax.InputSource;
public class XPathTest {
public static void main(String[] args) throws Exception {
String source = "<nfeProc xmlns=\"http://www.portalfiscal.inf.br/nfe\" versao=\"2.00\"></nfeProc>";
try {
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
NamespaceContext context = new NamespaceContext() {
private static final String PREFIX = "nfe";
private static final String URI = "http://www.portalfiscal.inf.br/nfe";
@Override
public String getNamespaceURI(String prefix) {
return (PREFIX.equals(prefix)) ? URI : XMLConstants.NULL_NS_URI;
}
@Override
public String getPrefix(String namespaceUri) {
return (URI.equals(namespaceUri)) ? PREFIX : XMLConstants.DEFAULT_NS_PREFIX;
}
@Override
public Iterator getPrefixes(String namespaceUri) {
return Collections.singletonList(this.getPrefix(namespaceUri)).iterator();
}
};
xPath.setNamespaceContext(context);
InputSource inputSource = new InputSource(new StringReader(source));
String versao = xPath.evaluate("//nfe:nfeProc/@versao", inputSource);
System.out.println(versao.toString());
} catch (XPathExpressionException e) {
e.printStackTrace();
}
}
}
これを実行すると、次の出力が得られます。
C:\Users\Luke\Java>java XPathTest
2.00