java用xpath解析XML

java用xpath解析XML
获取值为空

public class XmlToObject {
    public static void main(String[] args) throws Exception {
        String xml = "<ns2:SPSCertificate xmlns:ns2=\"urn:un:unece:uncefact:data:standard:SPSCertificate:5\" xmlns=\"urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:9\">\n" +
                "    <ns2:SPSExchangedDocument>\n" +
                "        <ID>NZL2014/AFFCO1/762648</ID>\n" +
                "\t<SignatorySPSAuthentication>\n" +
                "\t\t<IncludedSPSClause>\n" +
                "                <ID>1</ID>\n" +
                "                <Content languageID=\"en\">I hereby certify that the products:</Content>\n" +
                "                <Content languageID=\"zh\">本人在此证明该产品:</Content>\n" +
                "            </IncludedSPSClause>\n" +
                "\t</SignatorySPSAuthentication>\n" +
                "    </ns2:SPSExchangedDocument>\n" +
                "</ns2:SPSCertificate>";
        XPathFactory xpathFactory = XPathFactory.newInstance();
        XPath xpath = xpathFactory.newXPath();
        NzlSPSCertificateNamespaceContext namespaceContext = new NzlSPSCertificateNamespaceContext();
        xpath.setNamespaceContext(namespaceContext);
        //ns2:SPSCertificate/ns2:SPSExchangedDocument/default:ID
        XPathExpression expr = xpath.compile(
                "ns2:SPSCertificate/ns2:SPSExchangedDocument/default:SignatorySPSAuthentication/default:IncludedSPSClause\n" +
                        "[ID = '1']/default:Content[@languageID = 'zh']");
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        domFactory.setNamespaceAware(true);
        DocumentBuilder builder = domFactory.newDocumentBuilder();
        Document doc = builder.parse(new InputSource(new StringReader(xml)));
        NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            System.out.println(node.getTextContent());
        }
    }
}

class NzlSPSCertificateNamespaceContext implements NamespaceContext {
    @Override
    public String getNamespaceURI(String prefix) {
        if ("ns2".equals(prefix)) {
            return "urn:un:unece:uncefact:data:standard:SPSCertificate:5";
        } else if ("default".equals(prefix)) {
            return "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:9";
        }
        return null;
    }

    @Override
    public String getPrefix(String namespaceURI) {
        System.out.println(namespaceURI);
        throw new UnsupportedOperationException();
    }

    @Override
    public Iterator<String> getPrefixes(String namespaceURI) {
        throw new UnsupportedOperationException();
    }
}

xml结构是

<ns2:SPSCertificate xmlns:ns2="urn:un:unece:uncefact:data:standard:SPSCertificate:5" xmlns="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:9">
    <ns2:SPSExchangedDocument>
        <ID>NZL2014/AFFCO1/762648</ID>
    <SignatorySPSAuthentication>
        <IncludedSPSClause>
                <ID>1</ID>
                <Content languageID="en">I hereby certify that the products:</Content>
                <Content languageID="zh">本人在此证明该产品:</Content>
            </IncludedSPSClause>
    </SignatorySPSAuthentication>
    </ns2:SPSExchangedDocument>
</ns2:SPSCertificate>
        

用xpath取出"ns2:SPSCertificate/ns2:SPSExchangedDocument/SignatorySPSAuthentication/IncludedSPSClause
[ID = '1']/Content[@languageID = 'zh']"

打印下document给我看看

TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");

DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);


如果有用的话,请采纳下!!!
我刚才跑了下你的代码,有问题,获取不到数据,document是null。我给你改了下。

 public static void main(String[] args) throws Exception {
        String xml = "<ns2:SPSCertificate xmlns:ns2=\"urn:un:unece:uncefact:data:standard:SPSCertificate:5\" xmlns=\"urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:9\">\n" +
                "    <ns2:SPSExchangedDocument>\n" +
                "        <ID>NZL2014/AFFCO1/762648</ID>\n" +
                "    </ns2:SPSExchangedDocument>\n" +
                "</ns2:SPSCertificate>";
        try {
            // 创建DOM解析器工厂
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true);

            // 创建DOM解析器
            DocumentBuilder builder = factory.newDocumentBuilder();

            // 将XML字符串解析为Document对象
            Document document = builder.parse(new InputSource(new StringReader(xml)));

            // 获取根元素
            Element rootElement = document.getDocumentElement();

            // 获取ns2:SPSExchangedDocument元素
            Element spsExchangedDocumentElement = (Element) rootElement.getElementsByTagName("ns2:SPSExchangedDocument").item(0);

            // 获取ID元素
            Element idElement = (Element) spsExchangedDocumentElement.getElementsByTagName("ID").item(0);

            // 获取ID元素的文本内容
            String idValue = idElement.getTextContent();

            System.out.println("ID参数的值是:" + idValue);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

输出结果:ID参数的值是:NZL2014/AFFCO1/762648

img

引用 皆我百晓生 小程序回复内容作答:
你的代码基本上是正确的,但由于使用了命名空间,所以在编写XPath表达式时需要小心处理。你可以尝试以下修改来获取正确的值:

public class XmlToObject {
    public static void main(String[] args) throws Exception {
        String xml = "<ns2:SPSCertificate xmlns:ns2=\"urn:un:unece:uncefact:data:standard:SPSCertificate:5\" xmlns=\"urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:9\">\n" +
                "    <ns2:SPSExchangedDocument>\n" +
                "        <ID>NZL2014/AFFCO1/762648</ID>\n" +
                "    </ns2:SPSExchangedDocument>\n" +
                "</ns2:SPSCertificate>";
        XPathFactory xpathFactory = XPathFactory.newInstance();
        XPath xpath = xpathFactory.newXPath();
        xpath.setNamespaceContext(new NzlSPSCertificateNamespaceContext());
        XPathExpression expr = xpath.compile(
                "//ns2:SPSExchangedDocument/ID");
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        domFactory.setNamespaceAware(true);
        DocumentBuilder builder = domFactory.newDocumentBuilder();
        Document doc = builder.parse(new InputSource(new StringReader(xml)));
        NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            System.out.println(node.getTextContent());
        }
    }
}

class NzlSPSCertificateNamespaceContext implements NamespaceContext {
    @Override
    public String getNamespaceURI(String prefix) {
        if ("ns2".equals(prefix)) {
            return "urn:un:unece:uncefact:data:standard:SPSCertificate:5";
        } else if ("".equals(prefix)) {
            return "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:9";
        }
        return null;
    }

    @Override
    public String getPrefix(String namespaceURI) {
        if ("urn:un:unece:uncefact:data:standard:SPSCertificate:5".equals(namespaceURI)) {
            return "ns2";
        } else if ("urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:9".equals(namespaceURI)) {
            return "";
        }
        return null;
    }

    @Override
    public Iterator<String> getPrefixes(String namespaceURI) {
        throw new UnsupportedOperationException();
    }
}

请注意,XPath表达式中的//表示匹配任意深度的子节点,这样即使在命名空间的父节点上也能正常工作。这对于你的XML结构非常有用,因为它有多个命名空间级别。

通过以上修改,你应该能够正确获取到ID节点的文本内容。希望能对你有所帮助!


package com.vod.web.controller.system;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import java.io.StringReader;

public class XMLParser {
    public static void main(String[] args) {
        String xml = "<ns2:SPSCertificate xmlns:ns2=\"urn:un:unece:uncefact:data:standard:SPSCertificate:5\" xmlns=\"urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:9\">\n" +
                "    <ns2:SPSExchangedDocument>\n" +
                "        <ID>NZL2014/AFFCO1/762648</ID>\n" +
                "    </ns2:SPSExchangedDocument>\n" +
                "</ns2:SPSCertificate>";

        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(new InputSource(new StringReader(xml)));

            // 获取根元素
            Element rootElement = document.getDocumentElement();

            // 获取子元素
            NodeList nodeList = rootElement.getElementsByTagName("ID");
            if (nodeList.getLength() > 0) {
                Node idNode = nodeList.item(0);
                String id = idNode.getTextContent();
                System.out.println("ID: " + id);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

img

下是稍作修改后的代码示例,应该可以正确获取到ID的值

import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.*;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

public class XmlToObject {
    public static void main(String[] args) throws Exception {
        String xml = "<ns2:SPSCertificate xmlns:ns2=\"urn:un:unece:uncefact:data:standard:SPSCertificate:5\" xmlns=\"urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:9\">\n" +
                "    <ns2:SPSExchangedDocument>\n" +
                "        <ID>NZL2014/AFFCO1/762648</ID>\n" +
                "    </ns2:SPSExchangedDocument>\n" +
                "</ns2:SPSCertificate>";
        
        // 创建XPath对象
        XPathFactory xpathFactory = XPathFactory.newInstance();
        XPath xpath = xpathFactory.newXPath();
        xpath.setNamespaceContext(new NzlSPSCertificateNamespaceContext());
        
        // 编译XPath表达式
        XPathExpression expr = xpath.compile("/ns2:SPSCertificate/ns2:SPSExchangedDocument/ID");
        
        // 解析XML文档
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        domFactory.setNamespaceAware(true);
        DocumentBuilder builder = domFactory.newDocumentBuilder();
        Document doc = builder.parse(new InputSource(new StringReader(xml)));
        
        // 评估XPath表达式并获取节点列表
        NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
        
        // 遍历节点列表并输出文本内容
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            System.out.println(node.getTextContent());
        }
    }
}

class NzlSPSCertificateNamespaceContext implements NamespaceContext {
    @Override
    public String getNamespaceURI(String prefix) {
        if ("ns2".equals(prefix)) {
            return "urn:un:unece:uncefact:data:standard:SPSCertificate:5";
        } else if ("".equals(prefix)) {
            return "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:9";
        }
        return null;
    }

    @Override
    public String getPrefix(String namespaceURI) {
        if ("urn:un:unece:uncefact:data:standard:SPSCertificate:5".equals(namespaceURI)) {
            return "ns2";
        } else if ("urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:9".equals(namespaceURI)) {
            return "";
        }
        return null;
    }

    @Override
    public Iterator<String> getPrefixes(String namespaceURI) {
        throw new UnsupportedOperationException();
    }
}


该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
您的代码基本上是正确的,但是有一个小问题导致您无法获取到值。在使用XPath表达式时,您需要使用正确的命名空间前缀来匹配XML中的命名空间URI。

在您的代码中,您定义了NzlSPSCertificateNamespaceContext类来处理命名空间。根据您提供的XML,命名空间URI urn:un:unece:uncefact:data:standard:SPSCertificate:5 被分配给了 ns2 前缀。然而,在XPath表达式中,您使用了 ns2:SPSCertificate,而实际上应该是 ns2:SPSCertificate

请修改您的XPath表达式为 /ns2:SPSCertificate/ns2:SPSExchangedDocument/ns2:ID,然后再次运行代码。这样您应该能够成功获取到 <ID> 元素的值。

以下是修改后的代码:

public class XmlToObject {
    public static void main(String[] args) throws Exception {
        String xml = "<ns2:SPSCertificate xmlns:ns2=\"urn:un:unece:uncefact:data:standard:SPSCertificate:5\" xmlns=\"urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:9\">\n" +
                "    <ns2:SPSExchangedDocument>\n" +
                "        <ns2:ID>NZL2014/AFFCO1/762648</ns2:ID>\n" +
                "    </ns2:SPSExchangedDocument>\n" +
                "</ns2:SPSCertificate>";
        XPathFactory xpathFactory = XPathFactory.newInstance();
        XPath xpath = xpathFactory.newXPath();
        xpath.setNamespaceContext(new NzlSPSCertificateNamespaceContext());
        XPathExpression expr = xpath.compile(
                "/ns2:SPSCertificate/ns2:SPSExchangedDocument/ns2:ID");
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        domFactory.setNamespaceAware(true);
        DocumentBuilder builder = domFactory.newDocumentBuilder();
        Document doc = builder.parse(new InputSource(new StringReader(xml)));
        NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            System.out.println(node.getTextContent());
        }
    }
}

class NzlSPSCertificateNamespaceContext implements NamespaceContext {
    @Override
    public String getNamespaceURI(String prefix) {
        if ("ns2".equals(prefix)) {
            return "urn:un:unece:uncefact:data:standard:SPSCertificate:5";
        } else if ("".equals(prefix)) {
            return "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:9";
        }
        return null;
    }

    @Override
    public String getPrefix(String namespaceURI) {
        if ("urn:un:unece:uncefact:data:standard:SPSCertificate:5".equals(namespaceURI)) {
            return "ns2";
        } else if ("urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:9".equals(namespaceURI)) {
            return "";
        }
        return null;
    }

    @Override
    public Iterator<String> getPrefixes(String namespaceURI) {
        throw new UnsupportedOperationException();
    }
}

运行代码后,您应该能够成功获取到 <ID> 元素的值 "NZL2014/AFFCO1/762648"


如果以上回答对您有所帮助,点击一下采纳该答案~谢谢

java通过XPATH解析XML

package testXpath;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.NodeList;

public class TestXpathExample {
    public static void main(String args[]) throws FileNotFoundException, TransformerException, XPathExpressionException{
        TransformerFactory transFact = TransformerFactory.newInstance();
        Transformer transFormer = transFact.newTransformer();
        DOMResult dom = new DOMResult();
        transFormer.transform(new StreamSource(new FileInputStream(new File("test.xml"))), dom);
        
        XPath xpath = XPathFactory.newInstance().newXPath();
        
        @SuppressWarnings("serial")
        Map<String,String> prefix2uri = new HashMap<String,String>(){{
            
            put("foo","http://www.baidu.com");
            put("bar","http://www.google.com");
            
        }};
        
        @SuppressWarnings("serial")
        Map<String,String> uri2prefix = new HashMap<String,String>(){{
            put("http://www.baidu.com","foo");
            put("http://www.google.com","bar");
        }};
        
        
        xpath.setNamespaceContext(new NsSolver(prefix2uri,uri2prefix));
        
        XPathExpression expression = xpath.compile("//player");
        
        NodeList nodeList = (NodeList)expression.evaluate(dom.getNode(),XPathConstants.NODESET);
        
        for(int i = 0; i < nodeList.getLength(); i++){
            System.out.println(nodeList.item(i).getNodeName());
        }
    }
}

【以下回答由 GPT 生成】

使用Java中的XPath解析XML获取值为空

问题出在getPrefix方法上。根据XPath规范,getPrefix方法应该返回指定命名空间的前缀。因此,需要修改NzlSPSCertificateNamespaceContext类的getPrefix方法,使其正确返回命名空间的前缀。

以下是修改后的代码:

class NzlSPSCertificateNamespaceContext implements NamespaceContext {
    @Override
    public String getNamespaceURI(String prefix) {
        if ("ns2".equals(prefix)) {
            return "urn:un:unece:uncefact:data:standard:SPSCertificate:5";
        } else if ("".equals(prefix)) {
            return "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:9";
        }
        return null;
    }

    @Override
    public String getPrefix(String namespaceURI) {
        if ("urn:un:unece:uncefact:data:standard:SPSCertificate:5".equals(namespaceURI)) {
            return "ns2";
        } else if ("urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:9".equals(namespaceURI)) {
            return "";
        }
        return null;
    }

    @Override
    public Iterator<String> getPrefixes(String namespaceURI) {
        throw new UnsupportedOperationException();
    }
}

修改后的代码中,getPrefix方法根据命名空间的URI返回对应的前缀。这样,XPath解析器就能正确解析带有命名空间的XPath表达式,从而正确获取节点的值。

你可以重新运行代码,应该能够正确获取节点 <ID> 的值。



【相关推荐】



如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);


结合GPT给出回答如下请题主参考
假设我们有一个XML文件如下:

<students>
  <student>
    <name>Alice</name>
    <age>20</age>
  </student>
  <student>
    <name>Bob</name>
    <age>25</age>
  </student>
</students>

我们想要用Java的XPath来解析这个XML文件并获取每个学生的姓名和年龄。可以使用以下代码:

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class XmlToObject {
    public static void main(String[] args) throws Exception {
        // 创建Document对象
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        Document document = factory.newDocumentBuilder().parse("students.xml");

        // 创建XPath对象
        XPathFactory xPathFactory = XPathFactory.newInstance();
        XPath xPath = xPathFactory.newXPath();

        // 获取所有学生节点
        NodeList nodeList = (NodeList) xPath.evaluate("//student", document, XPathConstants.NODESET);
        for (int i = 0; i < nodeList.getLength(); i++) {
            Element student = (Element) nodeList.item(i);

            // 获取学生姓名和年龄
            String name = xPath.evaluate("name", student);
            String age = xPath.evaluate("age", student);

            System.out.println("Name: " + name + ", Age: " + age);
        }
    }
}

在上面的代码中,我们首先创建了一个Document对象来解析XML文件。接着,我们创建了一个XPath对象,使用evaluate()方法获取所有学生节点。对于每个学生节点,我们使用evaluate()方法获取学生姓名和年龄,并将它们打印出来。

如果你运行了上面的代码,却发现获取的值为空,有可能是XPath表达式有误或者XML文件解析错误。可以检查一下XPath表达式是否正确,或者尝试输出document对象来查看是否成功解析XML文件。