Java 如何从元素中获取值?

Java 如何从元素中获取值?,java,xml,xpath,Java,Xml,Xpath,我试图从字符串中获取一个值,这个源代码来自xml <nfeProc xmlns="http://www.portalfiscal.inf.br/nfe" versao="2.00"> 总是返回空值 我正在使用Java。您的问题在于XPath和名称空间 您的nfeProc元素位于URI为http://www.portalfiscal.inf.br/nfe。但是,在xPath中没有将任何前缀绑定到名称空间,因此它会在默认名称空间中搜索名为nfeProc的元素。没有这样的元素存在,所以你

我试图从字符串中获取一个值,这个源代码来自xml

<nfeProc xmlns="http://www.portalfiscal.inf.br/nfe" versao="2.00">
总是返回空值


我正在使用Java。

您的问题在于XPath和名称空间

您的
nfeProc
元素位于URI为
http://www.portalfiscal.inf.br/nfe
。但是,在
xPath
中没有将任何前缀绑定到名称空间,因此它会在默认名称空间中搜索名为
nfeProc
的元素。没有这样的元素存在,所以你什么也得不到

您需要做的是将前缀绑定到XPath对象和XML中的名称空间。在Java中,这是通过使用对象来完成的。然而,令人尴尬的是,NamespaceContext是一个接口,并且

另外请注意,在XPath中,未固定的名称(例如示例中的
nfeProc
)始终位于默认名称空间中(即具有空名称空间URI的名称空间)。无法将默认名称空间前缀重新绑定到其他URI,因此需要选择其他前缀,例如,
nfe
,然后在XPath中使用此前缀。这没有问题:如果
abc
xyz
都绑定到相同的命名空间URI,那么
abc:someElement
xyz:someElement
是相同的名称

@MostyMostacho正确地指出您的XPath表达式不太正确。计算
//nfe:nfeProc[@versao]
将返回具有
versao
属性的
nfe:nfeProc
元素的文本内容,但您需要该属性的值。因此,您需要的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();
        }
    }
}

您的问题在于XPath和名称空间

您的
nfeProc
元素位于URI为
http://www.portalfiscal.inf.br/nfe
。但是,在
xPath
中没有将任何前缀绑定到名称空间,因此它会在默认名称空间中搜索名为
nfeProc
的元素。没有这样的元素存在,所以你什么也得不到

您需要做的是将前缀绑定到XPath对象和XML中的名称空间。在Java中,这是通过使用对象来完成的。然而,令人尴尬的是,NamespaceContext是一个接口,并且

另外请注意,在XPath中,未固定的名称(例如示例中的
nfeProc
)始终位于默认名称空间中(即具有空名称空间URI的名称空间)。无法将默认名称空间前缀重新绑定到其他URI,因此需要选择其他前缀,例如,
nfe
,然后在XPath中使用此前缀。这没有问题:如果
abc
xyz
都绑定到相同的命名空间URI,那么
abc:someElement
xyz:someElement
是相同的名称

@MostyMostacho正确地指出您的XPath表达式不太正确。计算
//nfe:nfeProc[@versao]
将返回具有
versao
属性的
nfe:nfeProc
元素的文本内容,但您需要该属性的值。因此,您需要的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();
        }
    }
}

您的问题在于XPath和名称空间

您的
nfeProc
元素位于URI为
http://www.portalfiscal.inf.br/nfe
。但是,在
xPath
中没有将任何前缀绑定到名称空间,因此它会在默认名称空间中搜索名为
nfeProc
的元素。没有这样的元素存在,所以你什么也得不到

您需要做的是将前缀绑定到XPath对象和XML中的名称空间。在Java中,这是通过使用对象来完成的。然而,令人尴尬的是,NamespaceContext是一个接口,并且

另外请注意,在XPath中,未固定的名称(例如示例中的
nfeProc
)始终位于默认名称空间中(即具有空名称空间URI的名称空间)。无法将默认名称空间前缀重新绑定到其他URI,因此需要选择其他前缀,例如,
nfe
,然后在XPath中使用此前缀。这没有问题:如果
abc
xyz
都绑定到相同的命名空间URI,那么
abc:someElement
xyz:someElement
是相同的名称

@MostyMostacho正确地指出您的XPath表达式不太正确。计算
//nfe:nfeProc[@versao]
将返回具有
versao
属性的
nfe:nfeProc
元素的文本内容,但您需要该属性的值。因此,您需要的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();
        }
    }
}

您的问题在于XPath和名称空间

您的
nfeProc
元素位于URI为
http://www.portalfiscal.inf.br/nfe
。但是,在
xPath
中没有将任何前缀绑定到名称空间,因此它会在默认名称空间中搜索名为
nfeProc
的元素。没有这样的元素存在,所以你什么也得不到

您需要做的是绑定前缀t