我试图从String中获取一个值,这个源来自xml。
<nfeProc xmlns="http://www.portalfiscal.inf.br/nfe" versao="2.00">
所以我希望从versao
atributte获得价值。
我的代码是
try {
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
InputSource inputSource = new InputSource(new StringReader(source));
String versao = xPath.evaluate("//nfeProc[@versao]", inputSource);
versao.toString();
} catch (XPathExpressionException e) {
e.printStackTrace();
}
始终返回null
我在使用Java。
答案 0 :(得分:3)
您的问题在于XPath和命名空间。
您的nfeProc
元素位于名称空间中,其URI为http://www.portalfiscal.inf.br/nfe
。但是,您不会在xPath
中将任何前缀绑定到名称空间,因此它会在默认名称空间中搜索名为nfeProc
的元素。没有这样的元素,所以你什么也得不回来。
您需要做的是将前缀绑定到XPath对象中的命名空间以及XML中。在Java中,这是通过使用NamespaceContext对象完成的。然而,尴尬的是,NamespaceContext是一个接口,it isn't always easy getting hold of an implementation of it。
另外请注意,在XPath中,未加前缀的名称(例如示例中的nfeProc
)在默认名称空间中始终(即具有空名称空间URI的名称)。您不能将默认名称空间前缀重新绑定到其他URI,因此您需要选择另一个前缀,例如nfe
,然后在XPath中使用此前缀。这没有问题:如果abc
和xyz
都绑定到相同的名称空间URI,则abc:someElement
和xyz:someElement
的名称相同。
@MostyMostacho正确地指出你的XPath表达式不太正确。评估//nfe:nfeProc[@versao]
将返回具有nfe:nfeProc
属性的versao
元素的文本内容,但您需要此属性的值。所以,你想要的XPath表达式是//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