Reputation: 587
Infrastructure: I'm using JAVA 1.5 and this is mandatory. But i can load any external lib so no problem.
Problem:
I have an XML file recived via "an external channel" and I can use it as InputStream
if someone need to get the same, could use:
InputStream is = new FileInputStream(file);
I need to validate the XML against XSD that has neasted XSD
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:BODY="urn:CBI:xsd:CBIBdySDDReq.00.00.06"
xmlns:HTRT="urn:CBI:xsd:CBIHdrTrt.001.07"
xmlns:HE2E="urn:CBI:xsd:CBIHdrSrv.001.07"
xmlns:SGNT="urn:CBI:xsd:CBISgnInf.001.04"
xmlns:LMSG="urn:CBI:xsd:CBISDDReqLogMsg.00.00.06"
xmlns="urn:CBI:xsd:CBISDDReqPhyMsg.00.00.06"
targetNamespace="urn:CBI:xsd:CBISDDReqPhyMsg.00.00.06"
elementFormDefault="qualified">
<xs:import namespace="urn:CBI:xsd:CBIHdrTrt.001.07" schemaLocation="CBIHdrTrt.001.07.xsd"/>
<xs:import namespace="urn:CBI:xsd:CBIHdrSrv.001.07" schemaLocation="CBIHdrSrv.001.07.xsd"/>
<xs:import namespace="urn:CBI:xsd:CBIBdySDDReq.00.00.06" schemaLocation="CBIBdySDDReq.00.00.06.xsd"/>
<xs:element name="CBISDDReqPhyMsg" type="CBISDDReqPhyMsg.00.00.06">
<xs:annotation>
<xs:documentation>1. - Tag root dell'intero messaggio fisico di richiesta SDD CBI</xs:documentation>
</xs:annotation>
</xs:element>
<xs:complexType name="CBISDDReqPhyMsg.00.00.06">
<xs:sequence>
<xs:element name="CBIHdrTrt" type="HTRT:CBIHdrTrt.001.07">
<xs:annotation>
<xs:documentation>1.1. - Header di tratta CBI</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="CBIHdrSrv" type="HE2E:CBIHdrSrv.001.07">
<xs:annotation>
<xs:documentation>1.2. - Header di servizio CBI</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="CBIBdySDDReq" type="BODY:CBIBdySDDReq.00.00.06">
<xs:annotation>
<xs:documentation>1.3. - Body di servizio CBI</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
So I have a brunch of XSD file.
A chunk XML file is this
<?xml version="1.0" encoding="UTF-8"?>
<MSG:CBISDDReqPhyMsg xmlns:MSG="urn:CBI:xsd:CBISDDReqPhyMsg.00.00.06"
xmlns:HTRT="urn:CBI:xsd:CBIHdrTrt.001.07" xmlns:HE2E="urn:CBI:xsd:CBIHdrSrv.001.07"
xmlns:BODY="urn:CBI:xsd:CBIBdySDDReq.00.00.06" xmlns:LMSG="urn:CBI:xsd:CBISDDReqLogMsg.00.00.06"
xmlns:SGNT="urn:CBI:xsd:CBISgnInf.001.04" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MSG:CBIHdrTrt>
<HTRT:IdCBISndrf>0000636J</HTRT:IdCBISndrf>
<HTRT:IdCBIRcvrf>0000641V</HTRT:IdCBIRcvrf>
<HTRT:SrvNm>INC-SDDC</HTRT:SrvNm>
<HTRT:IdMsgTrt>
0000636JP12312111154007381042010010000636J000000636J0000641V0
</HTRT:IdMsgTrt>
So i need to validate the XML against CBISDDReqPhyMsg.00.00.06. So i know only at runtime against wich xml to use. Example another file could load CBISDDReqPhyMsg.00.00.05
I have two major problem
1) I need to obtain the xsd file name from XML and XML could be BIG 1/2GB (stax/sax are a nice solution)
2) I need to load the xsd from a jar because the whole app cannot have access to the file system.
For validation i prefer a system like http://www.edankert.com/validate.html
I read about include in this answer Problem validating an XML file using Java with an XSD having an include
But using the loader i can't obtain the infos about file.
Some idea?
Upvotes: 0
Views: 2622
Reputation: 14276
I have two major problem
1) I need to obtain the file name from XML and XML could be BIG 1/2GB
2) I need to load the xsd from a jar because the whole app cannot have access to the file system.
1.) The filename is not inside the XML...you should know what the filename of the XML is by other means (user input, hardcoded, etc.). If you have a directory full of only XML files, you could run a loop on the files. Some pseudo code:
for(getNextFile)
{
if(xmlValidationWithXSD(nextFile))
//passed validation
else
//failed validation
}
I usually run scripts to move all XML files from one place to XML-only folder.
2.) I believe StreamSource allows you to do this. Here's what I did recently:
public static boolean xmlValidationWithXSD(String xmlLocation){
Source xmlFile = new StreamSource(new File(xmlLocation));
//IMPORTANT: Here is what you need. Multiple XSDs (that relate to each other) AND getResource will access form .jar files
//Treat XSD as resource found in the class path, assume that the full package name is passed in xsdLocation
Source schemaFileSource1 = new StreamSource(BenefitEnrollmentRequestFileUtil.class.getResource(NEW_XSD_FILE_RESOURCE1).toString());
Source schemaFileSource2 = new StreamSource(BenefitEnrollmentRequestFileUtil.class.getResource(NEW_XSD_FILE_RESOURCE2).toString());
Source[] schemaFileSources = {schemaFileSource1, schemaFileSource2};
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
try {
Schema schema = schemaFactory.newSchema(schemaFileSources);
Validator validator = schema.newValidator();
validator.validate(xmlFile);
return true;
} catch (SAXException e) {
LOGGER.debug(xmlFile.getSystemId() + " is NOT valid", e);
LOGGER.debug("Reason: " + e.getLocalizedMessage());
} catch (IOException e) {
LOGGER.debug(xmlFile.getSystemId() + " is NOT valid", e);
LOGGER.debug("Reason: " + e.getLocalizedMessage());
}
return false;
}
Sources:
Referencing a XSD schema within jar file
Problem validating an XML file using Java with an XSD having an include
Edit:
the relation between file is the list contained in the first tag i have the list of xsd to use and the first xsd is the one that has the same namesace as the first tag
<MSG:CBISDDReqPhyMsg xmlns:MSG="urn:CBI:xsd:CBISDDReqPhyMsg.00.00.06" xmlns:HTRT="urn:CBI:xsd:CBIHdrTrt.001.07" xmlns:HE2E="urn:CBI:xsd:CBIHdrSrv.001.07" xmlns:BODY="urn:CBI:xsd:CBIBdySDDReq.00.00.06" xmlns:LMSG="urn:CBI:xsd:CBISDDReqLogMsg.00.00.06" xmlns:SGNT="urn:CBI:xsd:CBISgnInf.001.04" xmlns:xsi="w3.org/2001/XMLSchema-instance">;
Can't you read this first line in, then extract the data? Use a FileReader/DOM (it shouldn't be too slow if you're just reading one line) just to retrieve this one line. Then parse through the String. Create an ArrayList and add each individual piece you extract.
Check this out as far as efficiency goes:
https://stackoverflow.com/a/2134533/2498729
https://stackoverflow.com/a/12273296/2498729
Upvotes: 2