Pregunta

I'm having problems parsing XML.

I have the following method:

public void componentsInfoToSimulation(String houseDivision, String equipment) {
        Element root = doc.getRootElement();
        pt.ipp.isep.gecad.masgrip.Simulation.getHouseNamesOfComponents().add(equipment);

        for (Iterator i = root.elementIterator("house"); i.hasNext();) {
            Element element = (Element) i.next();

            if (element.attributeValue("id").equals(houseDivision)) {

                for (Iterator j = element.elementIterator("" + houseDivision); j.hasNext();) {
                    Element innerElement = (Element) j.next();

                    if (innerElement.attributeValue("id").equals(equipment)) {

                        for (Iterator k = innerElement.elementIterator("" + equipment); k.hasNext();) {
                            Element innerSubElement = (Element) k.next();

                            String op = innerSubElement.getQualifiedName();
                            switch (op) {
                                case "power":
                                    pt.ipp.isep.gecad.masgrip.Simulation.getHousePowerDosComponents().add(Integer.parseInt(innerSubElement.getTextTrim()));
                                    break;
                                case "min_power":
                                    pt.ipp.isep.gecad.masgrip.Simulation.getHouseMinPowerComponents().add(Integer.parseInt(innerSubElement.getTextTrim()));
                                    break;

                                case "max_power":
                                    pt.ipp.isep.gecad.masgrip.Simulation.getHouseMaxPowerComponents().add(Integer.parseInt(innerSubElement.getTextTrim()));
                                    break;

                                case "average_usage_hour":
                                    pt.ipp.isep.gecad.masgrip.Simulation.getHouseAverageUsageHoursPerDay().add(Float.parseFloat(innerSubElement.getTextTrim()));
                                    break;

                                case "average_usage_minute":
                                    pt.ipp.isep.gecad.masgrip.Simulation.getHouseAverageUsageMinutesPerDay().add(Float.parseFloat(innerSubElement.getTextTrim()));
                                    break;

                                default:
                                    break;
                            }
                        }
                    }
                }
            }
        }
        System.out.println("" + pt.ipp.isep.gecad.masgrip.Simulation.getHouseNamesOfComponents());
        System.out.println("" + pt.ipp.isep.gecad.masgrip.Simulation.getHousePowerDosComponents());
        System.out.println("" + pt.ipp.isep.gecad.masgrip.Simulation.getHouseMinPowerComponents());
        System.out.println("" + pt.ipp.isep.gecad.masgrip.Simulation.getHouseMaxPowerComponents());
        System.out.println("" + pt.ipp.isep.gecad.masgrip.Simulation.getHouseAverageUsageHoursPerDay());
        System.out.println("" + pt.ipp.isep.gecad.masgrip.Simulation.getHouseAverageUsageMinutesPerDay());

    }

And here's a sample of my XML file:

<components>
    <house id="Kitchen">
        <espresso_machine id="espresso machine">
            <power>360</power>
            <min_power>360</min_power>
            <max_power>360</max_power>
            <average_usage_hour>0.25</average_usage_hour>
            <average_usage_minute>15</average_usage_minute>
        </espresso_machine>
        <coffee_machine id="coffee machine">
            <power>1500</power>
            <min_power>800</min_power>
            <max_power>1500</max_power>
            <average_usage_hour>0.25</average_usage_hour>
            <average_usage_minute>15</average_usage_minute>
        </coffee_machine>
        <coffee_pot id="coffee pot">
            <power>0</power>
            <min_power>200</min_power>
            <max_power>200</max_power>
            <average_usage_hour>0.25</average_usage_hour>
            <average_usage_minute>15</average_usage_minute> 
        </coffee_pot>
    </house>
</components>

If I had to my program an "espresso machine" I should have the following output:

[espresso_machine] [360] [360] [360] [0.25] [15]

However, it comes out like this:

[espresso_machine] [] [] [] [] []

I thing the problem is in the Switch/Case when I use innerElement.getTextTrim() but I'm not sure. Can you help me fix this?

¿Fue útil?

Solución

There were a few errors in the code in how you were parsing the document and some things in your XML file that needed to be updated as well. See the below updated code and XML document. I added in comments so you could follow the logic.

Call to method:

componentsInfoToSimulation("Kitchen", "espresso machine");

Method:

 public static void componentsInfoToSimulation(String houseDivision, String equipment)
   {
      Element root = doc.getRootElement();

      // Iterate over the houses
      for (Iterator i = root.elementIterator("house"); i.hasNext();)
      {
         Element houseElement = (Element) i.next();

         // Check if the id of one the house elements equals the houseDivision
         String houseId = houseElement.attributeValue("id");
         if (houseId.equals(houseDivision))
         {
            // Iterate over the equipment for the house
            for (Iterator x = houseElement.elementIterator("equipment"); x.hasNext();)
            {
               Element equipmentElement = (Element) x.next();

               // Check if the id of one the equipment elements equals the
               // equipment
               String equipId = equipmentElement.attributeValue("id");
               if (equipId.equals(equipment))
               {
                  // Get all the elemnts and their values
                  int power = Integer.valueOf(equipmentElement.element("power").getTextTrim());
                  int minPower = Integer.valueOf(equipmentElement.element("min_power").getTextTrim());
                  int maxPower = Integer.valueOf(equipmentElement.element("max_power").getTextTrim());
                  float averageUsageHours = Float.valueOf(equipmentElement.element("average_usage_hour").getTextTrim());
                  float averageUsageMins = Float.valueOf(equipmentElement.element("average_usage_minute").getTextTrim());

                  // Update the model
                  pt.ipp.isep.gecad.masgrip.Simulation.getHouseNamesOfComponents().add(equipment);
                  pt.ipp.isep.gecad.masgrip.Simulation.getHousePowerDosComponents().add(power);
                  pt.ipp.isep.gecad.masgrip.Simulation.getHouseMinPowerComponents().add(minPower);
                  pt.ipp.isep.gecad.masgrip.Simulation.getHouseMaxPowerComponents().add(maxPower);
                  pt.ipp.isep.gecad.masgrip.Simulation.getHouseAverageUsageHoursPerDay().add(averageUsageHours);
                  pt.ipp.isep.gecad.masgrip.Simulation.getHouseAverageUsageMinutesPerDay().add(averageUsageMins);
               }
            }
         }
      }
   }

Notice how there are multiple equipment elements. They are identified by their ID. There was not a need to have all the elements different. They all represent a generic "equipment".

<components>
    <house id="Kitchen">
        <equipment id="espresso machine">
            <power>360</power>
            <min_power>360</min_power>
            <max_power>360</max_power>
            <average_usage_hour>0.25</average_usage_hour>
            <average_usage_minute>15</average_usage_minute>
        </equipment>
        <equipment id="coffee machine">
            <power>1500</power>
            <min_power>800</min_power>
            <max_power>1500</max_power>
            <average_usage_hour>0.25</average_usage_hour>
            <average_usage_minute>15</average_usage_minute>
        </equipment>
        <equipment id="coffee pot">
            <power>0</power>
            <min_power>200</min_power>
            <max_power>200</max_power>
            <average_usage_hour>0.25</average_usage_hour>
            <average_usage_minute>15</average_usage_minute> 
        </equipment>
    </house>
</components>

Otros consejos

This is just a recommendation to use XPath instead of explicit navigation. Cuts down the amount of code quite significantly:

    String expression = String.format(
            "/components/house[@id='%s']/*[@id='%s']/*", houseDivision,
            equipment);
    @SuppressWarnings("unchecked")
    List<Element> elements = doc.selectNodes(expression);
    for (Element e : elements) {
        switch (e.getName()) {
        case "power":
            break;
        case "min_power":
            break;
                    // etc
        }
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top