-1

The XML parser is not working and I'm getting the following error:

org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog. at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:257) at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:339) at openexcel.xmlreader.main(xmlreader.java:24)

Here is my XML document

</service>
 </services>
 <solutions>
      <solution>
           <cost>505.9214670746815</cost>
           <routes>
                <route>
                     <driverId>noDriver</driverId>
                     <vehicleId>1_1</vehicleId>
                     <start>0.0</start>
                     <act type="service">
                          <serviceId>5 WassimKarim maudarbaccus</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 Jean Nicolas Yung</serviceId>
                          <arrTime>109.98190391287031</arrTime>
                          <endTime>119.98190391287031</endTime>
                     </act>
                     <act type="service">
                          <serviceId>2 George Bush</serviceId>
                          <arrTime>119.98282618841856</arrTime>
                          <endTime>129.98282618841856</endTime>
                     </act>
                     <act type="service">
                          <serviceId>3 Saddam Usain</serviceId>
                          <arrTime>129.98343325287408</arrTime>
                          <endTime>139.98343325287408</endTime>
                     </act>
                     <act type="service">
                          <serviceId>1 Barack OBama</serviceId>
                          <arrTime>139.98435552842233</arrTime>
                          <endTime>149.98435552842233</endTime>
                     </act>
                     <end>259.9673220629237</end>
                </route>
           </routes>
      </solution>
      <solution>
           <cost>505.9208295302417</cost>
           <routes>
                <route>
                     <driverId>noDriver</driverId>
                     <vehicleId>1_2</vehicleId>
                     <start>0.0</start>
                     <act type="service">
                          <serviceId>5 Oppa Gamnamstyle</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 Jean Nicolas Yung</serviceId>
                          <arrTime>109.98190391287031</arrTime>
                          <endTime>119.98190391287031</endTime>
                     </act>
                     <act type="service">
                          <serviceId>2 Emilie Sparks</serviceId>
                          <arrTime>119.98282618841856</arrTime>
                          <endTime>129.98282618841856</endTime>
                     </act>
                     <act type="service">
                          <serviceId>1 Denzel Wshington</serviceId>
                          <arrTime>129.98372097890456</arrTime>
                          <endTime>139.98372097890456</endTime>
                     </act>
                     <act type="service">
                          <serviceId>3 Mona Lisa</serviceId>
                          <arrTime>139.9846432544528</arrTime>
                          <endTime>149.9846432544528</endTime>
                     </act>
                     <end>259.9668316441239</end>
                </route>
           </routes>
      </solution>
 </solutions>
</problem>

I'm trying to get several fields (cost,driverid,vehicleid,start,act,serviceId,arrTime) for every entity in the XML file.

What I've been trying so far is

marian0
  • 3,336
  • 3
  • 27
  • 37
Mattieu Kevin
  • 23
  • 1
  • 8
  • Where is the code? – ifly6 Feb 27 '18 at 17:41
  • How are you parsing it? Can you post your code? – nlopez Feb 27 '18 at 17:43
  • i'm having difficulties in implementing the code, can anyone help me just to understand the logic – Mattieu Kevin Feb 27 '18 at 17:51
  • 1
    XML parser is working fine: `` is not a valid beginning of an XML document. Your document is incomplete, i.e. you're missing the actual beginning that starts with something like `` or maybe just with `` – Andreas Feb 27 '18 at 18:05
  • Please edit your question to show the code you have so far. You should include at least an outline (but preferably a [Minimal, Complete, and Verifiable](https://stackoverflow.com/help/mcve) example of the code that you are having problems with, then we can try to help with the specific problem. You should also read [How to, Ask](https://stackoverflow.com/help/how-to-ask). – Gerardo BLANCO Feb 27 '18 at 18:29
  • @MattieuKevin I updated my answer, explaining where your error comes from and showing you how to extract the XML into Java objects. – Bentaye Feb 28 '18 at 10:07

1 Answers1

0

The Exception

The error you are getting is due to the fact that you XML is not well formed, the beginning of your XML does not seem correct, can you remove

</service>
</services>

and replace it by

<problem>

So that your XML starts this way:

<problem>
  <solutions>
    <solution>
      ..

This will match the end tags of your file

    </solution>
  </solutions>
</problem>

I tried it and it can now be parsed.

Extracting values

Once you have a valid XML, as explained above.

Let's say we have the following classes

class Solution {
  private Double cost;
  private List<Route> routes = new ArrayList<>();
  // Getters/Setters
}

class Route {
  private String driverId;
  private String vehicleId;
  private Double start;
  private Double end;
  private Act act;
  // Getters/Setters
}

class Act {
  private String type;
  private String serviceId;
  private Double arrTime;
  private Double endTime;
  // Getters/Setters
}

You need to create an handler which will build your object when reading the xml

class MyHandler extends DefaultHandler {

  // This will hold the result of the parsing
  private List<Solution> solutions = new ArrayList<>();

  // These are local variables used to create the objects
  private Solution solution;
  private Route route;
  private Act act;

  // The name of the element we are reading
  private String currentElementName = "";

  private static String SOLUTION_TAG = "solution";
  private static String ROUTE_TAG = "route";
  private static String ACT_TAG = "act";
  private static String COST_TAG = "cost";
  private static String DRIVERID_TAG = "driverId";
  private static String VEHICLEID_TAG = "vehicleId";
  private static String START_TAG = "start";
  private static String END_TAG = "end";
  private static String SERVICEID_TAG = "serviceId";
  private static String ARRTIME_TAG = "arrTime";
  private static String ENDTIME_TAG = "endTime";

  private static String ACT_TYPE_ATTRIBUTE = "type";

  public List<Solution> getSolutions() {
    return solutions;
  }

  // Called when we start a new element, that is where we create the objects
  public void startElement(String uri, String localName, String qName, Attributes attributes) {
    currentElementName = qName;
    if (qName.equalsIgnoreCase(SOLUTION_TAG)) {
      solution = new Solution();
    } else  if (qName.equalsIgnoreCase(ROUTE_TAG)) {
      route = new Route();
    } else  if (qName.equalsIgnoreCase(ACT_TAG)) {
      act = new Act();
      act.setType(attributes.getValue(ACT_TYPE_ATTRIBUTE));
    }
  }

  // Called when we ending an element, that is where we stick the objects one in an other
  public void endElement(String uri, String localName, String qName) {
    if (qName.equalsIgnoreCase(ACT_TAG)) {
      route.setAct(act);
    } else  if (qName.equalsIgnoreCase(ROUTE_TAG)) {
      solution.getRoutes().add(route);
    } else  if (qName.equalsIgnoreCase(SOLUTION_TAG)) {
      solutions.add(solution);
    }
    currentElementName = "";
  }

  // Called when we reading the text inside an element, that is where we set values to the object attributes
  public void characters(char ch[], int start, int length) {
    String s = new String(ch, start, length);
    if(currentElementName.equalsIgnoreCase(COST_TAG)) {
      solution.setCost(Double.valueOf(s));
    } else if(currentElementName.equalsIgnoreCase(DRIVERID_TAG)) {
      route.setDriverId(s);
    } else if(currentElementName.equalsIgnoreCase(VEHICLEID_TAG)) {
      route.setVehicleId(s);
    } else if(currentElementName.equalsIgnoreCase(START_TAG)) {
      route.setStart(Double.valueOf(s));
    } else if(currentElementName.equalsIgnoreCase(END_TAG)) {
      route.setEnd(Double.valueOf(s));
    } else if(currentElementName.equalsIgnoreCase(SERVICEID_TAG)) {
      act.setServiceId(s);
    } else if(currentElementName.equalsIgnoreCase(ARRTIME_TAG)) {
      act.setArrTime(Double.valueOf(s));
    } else if(currentElementName.equalsIgnoreCase(ENDTIME_TAG)) {
      act.setEndTime(Double.valueOf(s));
    }
  }
}

Then you can simply parse your XML this way:

MyHandler myHandler = new MyHandler();
try {
  SAXParserFactory factory = SAXParserFactory.newInstance();
  SAXParser saxParser = factory.newSAXParser();
  saxParser.parse(new InputSource(new StringReader(xml)), myHandler);
} catch (Exception e) {
  e.printStackTrace();
}

and you have all your files parsed into a list of Solutions in your handler, you can get it this way

myHandler.getSolutions();
Bentaye
  • 9,403
  • 5
  • 32
  • 45