0

文字列から 1 つの値を取得しようとしていますが、このソースは xml から取得されています。

<nfeProc xmlns="http://www.portalfiscal.inf.br/nfe" versao="2.00">

だから私は属性から値を取得したいversao

私のコードは

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を使用しています。

4

1 に答える 1

3

問題は XPath と名前空間にあります。

あなたのnfeProc要素は URI の名前空間にありますhttp://www.portalfiscal.inf.br/nfe。ただし、 の名前空間に接頭辞をバインドしないため、デフォルトの名前空間で名前がxPath付けられた要素が検索されます。nfeProcそのような要素は存在しないため、何も返されません。

必要なことは、XPath オブジェクトと XML の名前空間にプレフィックスをバインドすることです。Java では、これはNamespaceContextオブジェクトを使用して行われます。ただし、厄介なことに、NamespaceContext はインターフェースであり、その実装を把握するのは必ずしも容易ではありません

さらに、XPath ではnfeProc、例のようにプレフィックスのない名前は常にデフォルトの名前空間 (つまり、名前空間 URI が空の名前) にあることに注意してください。既定の名前空間プレフィックスを他の URI に再バインドすることはできないため、代わりに別のプレフィックス (たとえば、 ) を選択し、nfeこのプレフィックスを XPath で使用する必要があります。これには問題はありません。abcxyzが両方とも同じ名前空間 URI にバインドされている場合、abc:someElementxyz:someElementは同じ名前です。

@MostyMostacho は、XPath 式が正しくないことを正しく指摘しています。評価すると、属性を持つ要素//nfe:nfeProc[@versao]のテキスト コンテンツが返されますが、この属性の値が必要です。したがって、必要な XPath 式は です。(属性は親要素から名前空間を継承しないため、属性の名前はデフォルトの名前空間のままであることに注意してください。)nfe:nfeProcversao//nfe:nfeProc/@versaoversao

カスタム 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
于 2013-11-09T20:09:39.063 に答える