Java for循环从xml文档中获取子元素

问题描述 投票:0回答:1

我很难弄清楚如何编写一个循环来从给定的XML文档中检索值以简化我将给你一个xml文件的样本

</solution>
          <solution>
               <cost>505.9208295302417</cost>
               <routes>
                    <route>
                         <driverId>noDriver</driverId>
                         <vehicleId>1_1</vehicleId>
                         <start>0.0</start>
                         <act type="service">
                              <serviceId>5  </serviceId>
                              <arrTime>109.9819741964403</arrTime>
                              <endTime>119.9819741964403</endTime>
                         </act>
                         <end>229.9639483928806</end>
                    </route>
                    <route>
                         <driverId>noDriver</driverId>
                         <vehicleId>3_1</vehicleId>
                         <start>0.0</start>
                         <act type="service">
                              <serviceId>4  </serviceId>
                              <arrTime>109.98190391287031</arrTime>
                              <endTime>119.98190391287031</endTime>
                         </act>
                         <act type="service">
                              <serviceId>2 </serviceId>
                              <arrTime>119.98282618841856</arrTime>
                              <endTime>129.98282618841856</endTime>
                         </act>
                         <act type="service">
                              <serviceId>1 </serviceId>
                              <arrTime>129.98372097890456</arrTime>
                              <endTime>139.98372097890456</endTime>
                         </act>
                         <act type="service">
                              <serviceId>3 </serviceId>
                              <arrTime>139.9846432544528</arrTime>
                              <endTime>149.9846432544528</endTime>
                         </act>
                         <end>259.9668316441239</end>
                    </route>
               </routes>
          </solution>
     </solutions>

所以基本上我在代码中我将向您展示的是仅从有成本= 505.9208295302417的节点获取价值,请不要考虑这部分代码,所以下一步是检索driverid``, vehicleid and行为,我知道有一个缺少for循环但我不知道放在哪里!!请有人帮忙。我需要的所需输出就像每个vehicleid获取列表行为值一样

java代码

        public static void main(String[] args) {
        try {
            int totalVehicle;
            totalVehicle = 2;
            File fXmlFile = new File("C:/Users/HP/Desktop/solution.xml");
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(fXmlFile);
            doc.getDocumentElement().normalize();
            Double requiredCost = 505.9208295302417;
            System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
            // NodeList nList = doc.getElementsByTagName("route");
            System.out.println("----------------------------");
            NodeList nodeList = doc.getElementsByTagName("solution");
            for (int i = 0; i < nodeList.getLength(); i++) {

                Node solutionNode = nodeList.item(i);

                if (solutionNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element solutionElement = (Element) solutionNode;
                    Node costNode = solutionElement.getElementsByTagName("cost").item(0);
                    Node route = solutionElement.getElementsByTagName("routes").item(0);
                    // if correct cost, proceed to parse further
                    Double costValue = Double.valueOf(costNode.getTextContent());
                    if (Double.compare(requiredCost, costValue) == 0) {
                        System.out.println("working");
                        // there you go, found the node with the cost 505.9208295302417
                        // now just parse all the node elements you need here

                        System.out.println("cost : "
                                + solutionElement.getElementsByTagName("cost")
                                        .item(0).getTextContent());
                        for (int h = 0; h < totalVehicle; h++) {
                            System.out.println("DriverId : "
                                    + solutionElement.getElementsByTagName("driverId")
                                            .item(h).getTextContent().toString());
                            System.out.println("vehicleId : "
                                    + solutionElement.getElementsByTagName("vehicleId")
                                            .item(h).getTextContent());
NodeList optionList = solutionElement.getElementsByTagName("act");
                            System.out.println(optionList.getLength());

        for (int j = 0; j < optionList.getLength(); ++j)
        {

            for(int k =0;k<1;++k){
                Element option = (Element) optionList.item(j);
            String optionText = option.getTextContent();
           //address.add(optionText.replaceAll("[^A-Za-z]"," "));
            System.out.println("Citizen :"+optionText.replaceAll("[^A-Za-z]"," "));}
            ;


        }
java xml for-loop xmlreader domparser
1个回答
0
投票

正如其他人所建议的那样,使用xpath会容易得多,但如果绝对要求你循环使用所有这些东西,那就把问题分解成更小,更易于管理的部分。我想我会尝试一下,我有一个完整的,有效的解决方案来解决你的问题。

我们的想法是将xml分解为Java对象并使用这些对象来完成您需要的工作。

public static void main(String... args) throws SAXException, IOException, ParserConfigurationException {
    Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder()
            .parse(new File("/home/william/Documents/test.xml"));
    doc.getDocumentElement().normalize();

    NodeList nodeList = doc.getElementsByTagName("solution");
    for (int i = 0; i < nodeList.getLength(); i++) {
        Node solutionNode = nodeList.item(i);

        try {
            System.out.println(Solution.newInstance(solutionNode).toString());
        } catch (Exception e) {
            // do something
            e.printStackTrace();
        }   
    }
}

在这里,您的原始文档解析方式与解决方法相同,但解决方案是您自己的类,您可以将逻辑放入:

public class Solution {

    private final double cost;

    private final Collection<Route> routes;

    public static final Solution newInstance(Node solution) throws Exception {
        return new Solution(solution);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("solution:");
        sb.append(System.lineSeparator());
        sb.append("--------");
        sb.append(System.lineSeparator());
        sb.append("cost:");
        sb.append(this.cost);

        for (Route route : this.routes) {
            sb.append(route.toString());
        }

        return sb.toString();
    }

    private Solution(Node solution) throws Exception {
        if (solution.getNodeType() == Node.ELEMENT_NODE) {
            Element solutionElement = (Element) solution;
            this.cost = Double.valueOf(solutionElement.getElementsByTagName("cost").item(0).getTextContent());
            this.routes = Routes.get(solutionElement.getElementsByTagName("routes").item(0));
        } else {
            // TODO something?
            this.cost = 0D;
            this.routes = Collections.emptyList();
        }
    }
}

请注意,在main方法中,您需要检查成本。我已经将所有类变量getter方法都删除了,如果需要从对象外部读取它们,请添加所需的方法。所以例如在你的Solution类中添加一个getCost()方法然后在main方法中你可以检查适当的:if (solution.getCost() == requiredCost) { ...

在这里,根据您的要求,您可以根据需要向类成员添加getter。我刚刚覆盖了toString()方法,以便打印您可以阅读的内容。

Routes是一个util类,用于在Route节点的子节点之外创建<routes>对象的集合。

public class Routes {

    private final Collection<Route> items;

    public static Collection<Route> get(Node routes) throws Exception {
        return new Routes(routes).items;
    }

    private Routes() {
        this.items = new ArrayList<>();
    }

    private Routes(Node routes) throws Exception {
        this.items = new ArrayList<>();
        NodeList routesList = routes.getChildNodes();
        for (int i = 0; i < routesList.getLength(); i++) {
            Node route = routesList.item(i);
            if (Node.ELEMENT_NODE == route.getNodeType()) {
                items.add(Route.newInstance(route));
            } else {
                // TODO something?
            }
        }
    }   
}

Acts类与Routes类具有相似的逻辑(同样的事情,但对于行为):

public class Acts {

    private Collection<Act> items;

    public static Collection<Act> get(NodeList acts) throws Exception {
        return new Acts(acts).items;
    }

    private Acts() {
        this.items = new ArrayList<>();
    }

    private Acts(NodeList acts) throws Exception {
        this.items = new ArrayList<>();
        for (int i = 0; i < acts.getLength(); i++) {
            Node act = acts.item(i);
            if (Node.ELEMENT_NODE == act.getNodeType()) {
                this.items.add(Act.newInstance(act));
            } else {
                // TODO something?
            }
        }
    }
}

最后,每个人Act

public class Act {

    private final String service;

    private final double arrTime;

    private final double endTime;

    public static Act newInstance(Node act) throws Exception {
        return new Act(act);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();

        sb.append("Act");
        sb.append(System.lineSeparator());
        sb.append("arr time");
        sb.append(System.lineSeparator());
        sb.append(this.arrTime);
        sb.append(System.lineSeparator());
        sb.append("end time:");
        sb.append(System.lineSeparator());
        sb.append(this.endTime);
        sb.append(System.lineSeparator());
        sb.append("service:");
        sb.append(System.lineSeparator());
        sb.append(this.service);

        return sb.toString();
    }

    private Act(Node act) throws Exception {
        Element actElement = (Element) act;
        this.service = actElement.getAttribute("service");
        this.arrTime = Double.valueOf(actElement.getElementsByTagName("arrTime").item(0).getTextContent());
        this.endTime = Double.valueOf(actElement.getElementsByTagName("endTime").item(0).getTextContent());
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.