【问题标题】:An XPath expression in Java for getting xml elementsJava 中用于获取 xml 元素的 XPath 表达式
【发布时间】:2021-03-30 22:58:05
【问题描述】:

我想从一个包含 xml 元素的 api 中获取节点。

https://www.w3schools.com/xml/cd_catalog.xml这里是api的链接。

所以我的Java代码是这样的:

    package in.automationtesting.neh;
    
    import java.io.IOException;
    import java.io.Reader;
    import java.io.StringReader;
    import java.net.URI;
    import java.net.http.HttpClient;
    import java.net.http.HttpRequest;
    import java.net.http.HttpResponse;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    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.Document;
    import org.w3c.dom.NodeList;
    import org.xml.sax.InputSource;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    public class Test1 {
        
        
    
            public static final String GET_API_URL = "https://www.w3schools.com/xml/cd_catalog.xml";        
            
            public static void main(String[] args) throws IOException, InterruptedException {
                HttpClient client = HttpClient.newHttpClient();
                HttpRequest request = HttpRequest.newBuilder()
                        .GET()
                        .header("accept", "application/xml")
                        .uri(URI.create(GET_API_URL))
                        .build();
                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
                 
        
                 XPathFactory xpathfactory = XPathFactory.newInstance();
                 XPath xpath = xpathfactory.newXPath();
                 
                try {
    
                    Reader reader = new StringReader(response.body());
                    InputSource inputSource = new InputSource(reader);
                    XPath xpath1 = XPathFactory.newInstance().newXPath();
                    System.out.println(xpath1.evaluate("//CATALOG/CD", inputSource));
                    
                } catch (XPathExpressionException e) {
                    
                    e.printStackTrace();
                }

            }
}

控制台上的输出应该是这样的:

<CATALOG>
<CD>
<TITLE>1999 Grammy Nominees</TITLE>
<ARTIST>Many</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Grammy</COMPANY>
<PRICE>10.20</PRICE>
<YEAR>1999</YEAR>
</CD>


<CD>
<TITLE>Big Willie style</TITLE>
<ARTIST>Will Smith</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1997</YEAR>
</CD>
</CATALOG>

使用 xpath 表达式,我想获得 1995 年及以后发布的 cd,而且它们应该只来自美国。当我只匹配 xpath 表达式中的根目录时,它显示了所有好的元素,但是当我在它旁边添加 cd 时,在控制台上它只显示一张专辑而不是全部,我知道为什么我尝试在表达和其他变体中类似这样,但没有运气 "//CATALOG/CD[@year>1995 and country='USA']

【问题讨论】:

    标签: java xml xpath


    【解决方案1】:

    您必须使用NodeListXPathConstants.NODESET

    你的表情是/CATALOG/CD[COUNTRY='USA' and YEAR&gt;=1985] (“@”代表属性)

    语法是:

    import java.io.IOException;
    import java.io.Reader;
    import java.io.StringReader;
    import java.net.URI;
    import java.net.http.HttpClient;
    import java.net.http.HttpRequest;
    import java.net.http.HttpResponse;
    
    import javax.xml.xpath.XPathConstants;
    import javax.xml.xpath.XPathExpression;
    import javax.xml.xpath.XPathExpressionException;
    import javax.xml.xpath.XPathFactory;
    
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    import org.xml.sax.InputSource;
    
    public class Test1 {
    
        public static final String GET_API_URL = "https://www.w3schools.com/xml/cd_catalog.xml";
    
        public static void main(String[] args) throws IOException, InterruptedException {
    
            HttpClient client = HttpClient.newHttpClient();
            HttpRequest request = HttpRequest.newBuilder().GET().header("accept", "application/xml").uri(URI.create(GET_API_URL)).build();
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    
            try {
                Reader reader = new StringReader(response.body());
                InputSource inputSource = new InputSource(reader);
    
                XPath xpath = XPathFactory.newInstance().newXPath();
                XPathExpression expr = xpath.compile("/CATALOG/CD[COUNTRY='USA' and YEAR>=1985]");
                NodeList list = (NodeList)expr.evaluate(inputSource, XPathConstants.NODESET);
                
                for (int i = 0; i < list.getLength(); i++) {
                    Node node = list.item(i);
                    System.out.println(node.getTextContent());
                }
            }
            catch (XPathExpressionException e) {
                e.printStackTrace();
            }
        }
    }
    

    这给了:

    Empire Burlesque
    Bob Dylan
    USA
    Columbia
    10.90
    1985
    
    
    When a man loves a woman
    Percy Sledge
    USA
    Atlantic
    8.70
    1987
    
    
    1999 Grammy Nominees
    Many
    USA
    Grammy
    10.20
    1999
    
    
    Big Willie style
    Will Smith
    USA
    Columbia
    9.90
    1997
    
    
    Unchain my heart
    Joe Cocker
    USA
    EMI
    8.20
    1987
    

    【讨论】:

    • 非常感谢您的帮助。
    • 对不起,有没有办法像在输出示例中一样使用 xml 标签获取它们?
    【解决方案2】:

    此其他解决方案使用Transformer 来格式化输出。

    我找到了这个解决方案 herehere

    import java.io.IOException;
    import java.io.Reader;
    import java.io.StringReader;
    import java.io.StringWriter;
    import java.net.URI;
    import java.net.http.HttpClient;
    import java.net.http.HttpRequest;
    import java.net.http.HttpResponse;
    
    import javax.xml.transform.OutputKeys;
    import javax.xml.transform.Transformer;
    import javax.xml.transform.TransformerException;
    import javax.xml.transform.TransformerFactory;
    import javax.xml.transform.dom.DOMSource;
    import javax.xml.transform.stream.StreamResult;
    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;
    import org.xml.sax.InputSource;
    
    public class Test1 {
    
        public static final String GET_API_URL = "https://www.w3schools.com/xml/cd_catalog.xml";
    
        public static void main(String[] args) throws IOException, InterruptedException {
    
            HttpClient client = HttpClient.newHttpClient();
            HttpRequest request = HttpRequest.newBuilder().GET().header("accept", "application/xml").uri(URI.create(GET_API_URL)).build();
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    
            try {
                Reader reader = new StringReader(response.body());
                InputSource inputSource = new InputSource(reader);
    
                XPath xpath = XPathFactory.newInstance().newXPath();
                XPathExpression expr = xpath.compile("/CATALOG/CD[COUNTRY='USA' and YEAR>=1985]");
                NodeList list = (NodeList)expr.evaluate(inputSource, XPathConstants.NODESET);
    
                Transformer transformer = TransformerFactory.newInstance().newTransformer();
                transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
                transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
                
                for (int i = 0; i < list.getLength(); i++) {
                    StringWriter writer = new StringWriter();
                    transformer.transform(new DOMSource(list.item(i)), new StreamResult(writer));
                    System.out.println(writer.toString());
                }
            }
            catch (XPathExpressionException | TransformerException e) {
                e.printStackTrace();
            }
        }
    }
    

    现在的结果是:

    <CD>
        <TITLE>Empire Burlesque</TITLE>
        <ARTIST>Bob Dylan</ARTIST>
        <COUNTRY>USA</COUNTRY>
        <COMPANY>Columbia</COMPANY>
        <PRICE>10.90</PRICE>
        <YEAR>1985</YEAR>
      </CD>
    <CD>
        <TITLE>When a man loves a woman</TITLE>
        <ARTIST>Percy Sledge</ARTIST>
        <COUNTRY>USA</COUNTRY>
        <COMPANY>Atlantic</COMPANY>
        <PRICE>8.70</PRICE>
        <YEAR>1987</YEAR>
      </CD>
    <CD>
        <TITLE>1999 Grammy Nominees</TITLE>
        <ARTIST>Many</ARTIST>
        <COUNTRY>USA</COUNTRY>
        <COMPANY>Grammy</COMPANY>
        <PRICE>10.20</PRICE>
        <YEAR>1999</YEAR>
      </CD>
    <CD>
        <TITLE>Big Willie style</TITLE>
        <ARTIST>Will Smith</ARTIST>
        <COUNTRY>USA</COUNTRY>
        <COMPANY>Columbia</COMPANY>
        <PRICE>9.90</PRICE>
        <YEAR>1997</YEAR>
      </CD>
    <CD>
        <TITLE>Unchain my heart</TITLE>
        <ARTIST>Joe Cocker</ARTIST>
        <COUNTRY>USA</COUNTRY>
        <COMPANY>EMI</COMPANY>
        <PRICE>8.20</PRICE>
        <YEAR>1987</YEAR>
      </CD>
    

    【讨论】:

      猜你喜欢
      • 2021-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-14
      相关资源
      最近更新 更多