在Java中使用XPath解析XML

时间:2015-10-05 18:08:46

标签: java xml xpath

我想解析这个XML文件:

 <NameDefinitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="../Documents/Calcs/FriendlyNames.xsd">


     <NameDefinition>
         <ID>/Temporary/EIC/EICWorksheetPP/WagesLessThanAdjustments</ID>
         <Name>you have more income that doesn't count than income that counts</Name>
         <BooleanPhrases>
             <True><Text>you have more income that doesn't count than income that counts</Text></True>
             <False><Text>you have more income that counts than income that doesn't count</Text></False>
             <Blank><Text>we don't if you have more income that doesn't count than income that counts</Text></Blank>
         </BooleanPhrases>
         <BooleanQuestions>
             <True><Text>Why do I have more income that doesn't count than income that counts?</Text></True>
             <False><Text>Why do I have more income that counts than income that doesn't count?</Text></False>
             <Blank><Text>Why don't you know if I have more income that doesn't count than income that counts?</Text></Blank>
         </BooleanQuestions>
     </NameDefinition>


     <NameDefinition>
         <ID>/Temporary/EIC/HaveInaccurateInfo</ID>
         <Name>you told us your info is incorrect</Name>
         <BooleanPhrases>
             <True><Text>you told us some of your info is incorrect</Text></True>
             <False><Text>you told us your info is correct</Text></False>
             <Blank><Text>we don't know whether your info is correct</Text></Blank>
         </BooleanPhrases>
         <BooleanQuestions>
             <True><Text>Why is some of my info incorrect?</Text></True>
             <False><Text>Why is my info correct?</Text></False>
             <Blank><Text>Why don't you know if my info is correct?</Text></Blank>
         </BooleanQuestions>
     </NameDefinition>

</NameDefinitions>

获取IDName个节点的值。我想返回的数据结构为Map(String,String),因此ID是关键,Name是值。

如何在Java 6中实现这一目标?

编辑:

这是我当前的实现,但是

static Map<String, String> parse(String pathToFriendlyNamesFile) 
        throws IOException, 
        XPathExpressionException { 

    XPath xpath = XPathFactory.newInstance().newXPath();
    Map<String, String> map = new LinkedHashMap<String,String>();

    InputStream file = null;

    try {
        file = new BufferedInputStream(Files.newInputStream(Paths.get(pathToFriendlyNamesFile)));
        InputSource inputSource = new InputSource(file);

        NodeList nodeIDList = (NodeList) xpath.evaluate("//NameDefinition/ID", inputSource, XPathConstants.NODESET);
        NodeList nodeNameList = (NodeList) xpath.evaluate("//NameDefinition/Name", inputSource, XPathConstants.NODESET);

        int nodeCount = nodeIDList.getLength();
        System.out.println("Node count: "+nodeCount);
        for(int i=0;i<nodeCount;i++) {

            Node nodeID = nodeIDList.item(i);
            Node nodeName = nodeNameList.item(i);

            String id = nodeID.getTextContent();
            String name = nodeName.getTextContent();
            map.put(id, name);
        }

    } catch (IOException e) {
        e.printStackTrace();
    } catch (XPathExpressionException e) {
        e.printStackTrace();
    } finally {
        file.close();
    }
    return map;
}

例外:

java.io.IOException: Stream closed
    at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:162)
    at java.io.BufferedInputStream.fill(BufferedInputStream.java:206)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:254)

javax.xml.xpath.XPathExpressionException: java.io.IOException: Stream closed
    at org.apache.xpath.jaxp.XPathImpl.evaluate(XPathImpl.java:481)

Caused by: java.io.IOException: Stream closed
    at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:162)
    at java.io.BufferedInputStream.fill(BufferedInputStream.java:206)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:254)

我关闭了流但显然仍然存在问题?

2 个答案:

答案 0 :(得分:1)

//对于像DocumenttBuilderFactory这样的下面的类使用xml-apis.jar。

//XPATH expressions
public static final String IdExpr = "/NameDefinition/@Id";
public static final String NameExpr = "/NameDefinition/@Name";

Map<String,String> evaluateXML(String file, String IdExpr, String NameExpr) {
    Map < String,
    String > returnMap = null;
    try {
        FileInputStream fis = new FileInputStream(new File(file));

        DocumentBuilderFactory builderFactory = DocumentBuilderFactory
            .newInstance();
        DocumentBuilder builder = builderFactory.newDocumentBuilder();
        Document xmlDocument = builder.parse(fis);

        XPath xPath = XPathFactory.newInstance().newXPath();

        String Id = xPath.compile(IdExpr).evaluate(
                xmlDocument);
        String Name = xPath.compile(NameExpr).evaluate(
                xmlDocument);

        returnMap = new HashMap < String,
        String > ();

        returnMap.put(Id, Name);
    }

答案 1 :(得分:0)

解决方案是前进的,我应该在发布这个问题之前做一些研究:

static Map<String,String> parseDoc(String pathToFriendlyNamesFile) 
        throws ParserConfigurationException, 
        SAXException, 
        IOException {

    File f = new File(pathToFriendlyNamesFile); 
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    DocumentBuilder db = dbf.newDocumentBuilder();
    Document doc = db.parse(f);

    Map<String,String> map = new LinkedHashMap<String, String>();

    doc.getDocumentElement().normalize();

    System.out.println("Root Element: "+doc.getDocumentElement().getNodeName());

    NodeList nList = doc.getElementsByTagName("NameDefinition");
    System.out.println("How many nodes? "+nList.getLength());
    for(int i=0;i<nList.getLength();i++) {
        Node nNode = nList.item(i);

        if(nNode.getNodeType() == Node.ELEMENT_NODE) {
            Element eElement = (Element) nNode;
            String nodeID = eElement.getElementsByTagName("ID").item(0).getTextContent();
            String name = eElement.getElementsByTagName("Name").item(0).getTextContent();

            System.out.println("ID: "+nodeID+" Name: "+name);
            map.put(nodeID, name);
        }
    }

    return map;
}