3

I've read a bunch of similar posts, but i can't find a solution for my problem: i need to validate and parse xml files. (validation against xsd schema). The problem is that on my approach, when i run: mvn package and then run the jar file i get the following error:

java.lang.IllegalArgumentException: URI is not hierarchical
    at java.io.File.<init>(Unknown Source)
    at com.test.Main.main(Main.java:15)

Here is what i tried:

Later EDIT: source code

How can I pass an InputStream as parameter for multiple methods without getting stream closed exception? It is a correct approach?

public class DOMParserFile {

  private InputStream   inputXML;
  private InputStream inputXSD;
  private Set<CarPart> carParts;

  public DOMParserFile(InputStream xmlFile, InputStream xsdFile) {
    this.inputXML = xmlFile;
    this.inputXSD = xsdFile;
    carParts = new HashSet<CarPart>();
 }


 public void readFromXMLFile() throws Exception {

    if (XMLFileValidator.validateAgainstXSD(inputXML, inputXSD)) {

        DocumentBuilderFactory builderFactory = DocumentBuilderFactory
                .newInstance();
        DocumentBuilder builder = builderFactory
                .newDocumentBuilder();
        Document doc = builder.parse(inputXML);

        // get the carPart nodes
        NodeList carPartList = doc.getElementsByTagName("carPart");
        // store car parts into a list
        for (int i = 0; i < carPartList.getLength(); i++) {
            // build new car part object
            CarPart carPart = new CarPart();
            Node carPartNode = carPartList.item(i);
            if (carPartNode.getNodeType() == Node.ELEMENT_NODE) {
                Element elem = (Element) carPartNode;
                // set id
                carPart.setId(elem.getElementsByTagName("id").item(0)
                        .getTextContent());
                // set name
                carPart.setName(elem.getElementsByTagName("name").item(0)
                        .getTextContent());
                // set description
                carPart.setDescription(elem
                        .getElementsByTagName("description").item(0)
                        .getTextContent());
                // set quantity
                carPart.setQuantity(Integer.valueOf(elem
                        .getElementsByTagName("quantity").item(0)
                        .getTextContent()));
                // set manufacturer
                carPart.setPartManufact(elem
                        .getElementsByTagName("partManufacturer").item(0)
                        .getTextContent());
                // set price
                carPart.setPrice(Double.valueOf(elem
                        .getElementsByTagName("price").item(0)
                        .getTextContent()));
                // get the list of available vehicles
                NodeList vehicleNodeList = ((Element) carPartNode)
                        .getElementsByTagName("availableFor");
                Set<Vehicle> availableVehicles = new HashSet<Vehicle>();
                for (int j = 0; j < vehicleNodeList.getLength(); j++) {
                    Vehicle vehicle = new Vehicle();
                    Node vehicleNode = vehicleNodeList.item(j);
                    if (vehicleNode.getNodeType() == Node.ELEMENT_NODE) {
                        Element vehicleELement = (Element) vehicleNode;
                        // set vehicle's make
                        vehicle.setMake(vehicleELement
                                .getElementsByTagName("make").item(0)
                                .getTextContent());
                        // set vehicle's model
                        vehicle.setModel(vehicleELement
                                .getElementsByTagName("model").item(0)
                                .getTextContent());
                        // get the available list of years of fabrication
                        // for
                        // this vehicle
                        NodeList yearsList = ((Element) vehicleNode)
                                .getElementsByTagName("fabricationYear");
                        Set<Integer> years = new HashSet<Integer>();
                        for (int k = 0; k < yearsList.getLength(); k++) {
                            Node yearNode = yearsList.item(k);
                            if (yearNode.getNodeType() == Node.ELEMENT_NODE) {
                                Element yearElem = (Element) yearNode;
                                years.add(Integer.valueOf(yearElem
                                        .getAttribute("yearAttr")));
                            }
                        }
                        vehicle.setFabYears(years);
                        availableVehicles.add(vehicle);
                    }

                }
                carPart.setVehicles(availableVehicles);
            }
            carParts.add(carPart);
        }
    }

}

public void printCarParts(){
    for(CarPart p :carParts){
        p.output();
    }
}

}

XMLFileValidator class

public class XMLFileValidator {


public static boolean validateAgainstXSD(InputStream xmlFile, InputStream xsdFile)
{
    try
    {
        SchemaFactory factory = 
            SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema schema = factory.newSchema(new StreamSource(xsdFile));
        Validator validator = schema.newValidator();
        validator.validate(new StreamSource(xmlFile));
        System.out.println("The XML file IS valid");
        return true;
    }
    catch(Exception ex)
    {
        System.out.println("The XML file is NOT valid");
        System.out.println("Reason: " + ex.getLocalizedMessage());
        ex.printStackTrace();
        return false;
    }
  }
}

Main class

public class Main {

   public static void main(String args[]){  


    try {

        InputStream inXML = Main.class.getResourceAsStream("/xml/carParts.xml");
        InputStream inXSD = Main.class.getResourceAsStream("/xml/carPartsWarehouse.xsd");





        //1. dom parsing method
        System.out.println("**********************DOM PARSING METHOD************************");
        DOMParserFile dom = new DOMParserFile(inXML,inXSD);
        dom.readFromXMLFile();
        dom.printCarParts();

        //2. sax parsing method
        System.out.println("***********************SAX PARSING METHOD*************************");
        SAXParserFile sax = new SAXParserFile(inXML,inXSD);
        sax.readDataFromXml();
        sax.printCarParts();

        //3. stax parsing method
        System.out.println("***********************StAX PARSING METHOD*************************");
        StAXParserFile stax = new StAXParserFile(inXML,inXSD);
        stax.readFromXml();
        stax.printCarParts();

    } catch (URISyntaxException e1) {
        e1.printStackTrace();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }       
}
laura
  • 2,085
  • 13
  • 36
  • 68
  • Where is `DOMParserFile` located? – Willem Van Onsem Feb 19 '15 at 19:47
  • @CommuSoft I modified the code as you suggested using InputStream and now i have a problem on passing the same stream as parameter for DOMParser, SAXParser and StAXParser. I get `java.io.IOException: Stream closed`. Can you help me with that? – laura Feb 21 '15 at 17:15
  • Can you modify the answer and provide the full source code? – Willem Van Onsem Feb 21 '15 at 17:31
  • well, a stream reads from start to end so after the first parser has read info, the cursor is located at the end of the stream. So you should either call `inXML.reset()` and `inXSD.reset()` between two reads, or construct a new `InputStream`. – Willem Van Onsem Feb 21 '15 at 17:48

1 Answers1

3

Well these are not really Files, they are embedded resources.

You can open them manually since .jar's are .zip files where the resources are files. But that's not an elegant way to process them.

You can however open then as Stream. So:

InputStream s = Main.class.getResourceAsStream("/xml/carParts.xml");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(s);
//process document
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555