validation a xml with several xsd schema DOM java - java

After search on internet and in differnets forums, have not found my answer.
I have a XML file which is define by two XSD schema.
For write the XML file, there are two ways to write the XML file :
(I have to delete the "<" charactere to display the XML file)
First methode to write it :
?xml version="1.0" encoding="UTF-8" standalone="yes"?>
Policy xmlns="http://www.W3C.com/Policy/v3#" xmlns:ns2="http://www.W3C.com /PolicyExtension/v3#">
DigestAlg Algorithm="http://test"/>
Transforms>
Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n20010315"></Transform>
/Transforms>
ns2:Validation>
ns2:ConditionID>1.0.1</ns2:ConditionID>
ns2:TConditionID>1.0.2</ns2:TConditionID>
/ns2:Validation>
/Policy>"
second methodes :
?xml version="1.0" encoding="UTF-8" standalone="yes"?>
Policy xmlns="http://www.W3C.com/Policy/v3#">
DigestAlg Algorithm="http://test"/>
Transforms>
Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n20010315"></Transform>
/Transforms>
Validation xmlns:ns2="http://www.W3C.com/PolicyExtension/v3#">
ConditionID>1.0.1</ns2:ConditionID>
TConditionID>1.0.2</ns2:TConditionID>
/Validation>
/Policy>
For pasring my XML files, i use :
InputStream doc = new FileInputStream(myXMLFile);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
List<Source> sourceListSchema = new ArrayList<Source>();
sourceListSchema.add(new StreamSource(SignaturePolicy.class.getResourceAsStream(MY_XSD_SCHEMA_1)));
sourceListSchema.add(new StreamSource(SignaturePolicy.class.getResourceAsStream(MY_XSD_SCHEMA_2)));
Schema schema;
try {
Source[] sourceTmp = new Source[1];
schema = sf.newSchema(sourceListSchema.toArray(sourceTmp));
} catch (SAXException e) {
LogMachine.logger.severe(
"SAXException : The schema can not be parse :"+e.getMessage());
}
dbf.setIgnoringElementContentWhitespace(true);
dbf.setNamespaceAware(true);
dbf.setIgnoringComments(true);
dbf.setSchema(schema);
DocumentBuilder db;
try {
db = dbf.newDocumentBuilder();
documentPolicy = db.parse(Doc);
} catch (ParserConfigurationException e) {
LogMachine.logger.severe(
"ParserConfigurationException : the file can not be parse by DOM :"+e.getMessage());
} catch (SAXException e) {
LogMachine.logger.severe(
"SAXException : the file can not be parse by DOM :"+e.getMessage());
} catch (IOException e) {
LogMachine.logger.severe(
"IOException : the file can not be open like a file :"+e.getMessage());
}
When I want to parse this documents with DOM, the first XML file display an error
Exception in thread "main" org.w3c.dom.ls.LSException: The prefix "ns2" for element "ns2:Validation" is not bound.
But the second XML file is well parse.
Someone can help me to parse the two documents ??
Thank you for you help

Related

JAXB unmarshal: unexpected element

Background:
I am using JAXB to unmarshal XML into Java objects. Originally, I was using just JAXB to perform the unmarshal. Then a static analysis was performed on the code and a high criticality issue was raised for XML External Entity Injection. After a little research, I found a suggestion (https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#JAXB_Unmarshaller) to use a parser configured to prevent external entities from being parsed. An example of what to do was provided:
//Disable XXE
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
//Do unmarshall operation
Source xmlSource = new SAXSource(spf.newSAXParser().getXMLReader(), new InputSource(new StringReader(xml)));
JAXBContext jc = JAXBContext.newInstance(Object.class);
Unmarshaller um = jc.createUnmarshaller();
um.unmarshal(xmlSource);
I have not done this exactly as shown, but I believe I have done the same in effect:
XMLReader reader = getXMLReader();
if (reader == null) {
logger.warn("Unable to create XML reader");
return;
}
JAXBContext context = JAXBContext.newInstance(messageClass);
Unmarshaller unmarshaller = context.createUnmarshaller();
for (File file : files) {
try {
InputSource source = new InputSource(new FileReader(file));
Source xmlSource = new SAXSource(reader, source);
JAXBElement<? extends BaseType> object =
(JAXBElement<? extends BaseType>) unmarshaller.unmarshal(xmlSource);
messages.add(object.getValue());
} catch (FileNotFoundException e) {
logger.error("Exception", e);
}
}
...
private XMLReader getXMLReader() {
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
} catch (SAXNotRecognizedException | SAXNotSupportedException
| ParserConfigurationException e) {
logger.error("Exception", e);
}
XMLReader reader = null;
try {
reader = factory.newSAXParser().getXMLReader();
} catch (SAXException | ParserConfigurationException e) {
logger.error("Exception", e);
}
return reader;
}
Problem:
After implementing the correction, I am now getting an unmarshal exception when the program attempts to read in XML:
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"ns1:TypeXYZ"). Expected elements are <{protected namespace URI}TypeABC>,...<{protected namespace URI}TypeXYZ>,...
Before the above fix where I was just using JAXB to unmarshal, it was able to properly parse the provided XML with no problem.
I assume that the SAX parser expects the XML to provide extra information that's missing, or that it needs to be configured to ignore whatever it's complaining about. I tried a few other "features" (http://xml.org/sax/features/namespace-prefixes=true and http://xml.org/sax/features/validation=false), but that did not resolve the problem.
I have no control over the XML schema that defines the XML types, nor do I have control over how the corresponding Java classes are generated.
Any information to help me understand what's going on and that helps me resolve this problem, would be very much appreciated.
After a little experimentation I was able to resolve the error by setting the following features:
factory.setFeature("http://xml.org/sax/features/validation", false);
factory.setFeature("http://xml.org/sax/features/namespaces", true);
factory.setFeature("http://xml.org/sax/features/namespace-prefixes", true);

Java parse a xml with file drop

Having the filedrop already implemented in my code, I need to parse the xml file I drop in the main().
Main()
case "XML":
text.append("Processing file type XML: "+files[i].getCanonicalPath() + "\n" );
ReadXml read_xml = new ReadXml();
read_xml.read(files[i].getCanonicalPath(), text);
break;
ReadXml.java
public class ReadXml {
ProgramDocument programDocument = new ProgramDocument();
public void read(String FILE, javax.swing.JTextArea text ) {
try {
JAXBContext context = JAXBContext.newInstance(ProgramDocument.class);
Unmarshaller u = context.createUnmarshaller();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(FILE);
Object o = u.unmarshal( doc );
doc.getDocumentElement().normalize();
text.append("Account : " +doc.getElementsByTagName("Account").item(0));
}
catch(Exception e) {
text.append("XML file not parsed correctly.\n");
}
}
}
I am not able to print anything, and when I am, I see "NULL" or just empty row or some path#numbers
I am not a developer, I just need to try opening a xml a send contents to a DB, but this is too far already.
EDIT: added part of xml
<?xml version="1.0" encoding="UTF-8"?>
<ARRCD Version="48885" Release="38">
<Identification v="ORCOZIO"/>
<Version v="013"/>
<Account v="OCTO">
<Type v="MAJO"/>
<Date v="2016-05-14"/>
</AARCD>
There are no elements tagged "Account" in the element "Account".
What you want to read here are the Attributes of Account, not other elements.
Thus you should use eElement.getAttribute("v") if you want to read attribute v, not getElementsByTagName()

Tell JAXP the path to DTD file

I have xml files with a reference to a dtd file.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE varman SYSTEM "referenced.dtd">
...
I managed to read this files with JAXP, but only if referenced.dtd is located in the same folder as the xml file. Otherwise I get an exception that the dtd file could not be loaded. And I could not find the place where to insert a handler or anything to resolve this missing resource. Please give me enlightment!
Use the properties settings to allow external paths:
jaxp properties
Add an error handler to catch unsupported properties:
public boolean isNewPropertySupported() {
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser parser = spf.newSAXParser();
parser.setProperty("http://javax.xml.XMLConstants/property/accessExternalDTD", "file");
} catch (ParserConfigurationException ex) {
fail(ex.getMessage());
} catch (SAXException ex) {
String err = ex.getMessage();
if (err.indexOf("Property 'http://javax.xml.XMLConstants/property/accessExternalDTD' is not recognized.") > -1)
{
//expected, jaxp 1.5 not supported
return false;
}
}
return true;
}

Can't seem to parse a xml file in android without getting a saxparser unexpected token error

I've been fighting trying to parse a basic xml file in a little test android app.
The code I have is the following:
InputStream is = getResources().openRawResource(R.xml.content);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(is,"UTF-8"); //Blows up right here.
// Bunch more stuff here
}
My xml looks like the following:
<?xml version="1.0" ?>
<main>
<background>
<defintion>This is a test</defintion>
</background>
</main>
The problem is that when I try to parse this I get an org.xml.sax.SAXParseException: Unexpected token (position:TEXT unprintable characters here ...#3:252 in java.io.InputStreamReader#411f3898) error.
I googled around and all the other solutions I found don't seem to work.
I double checked that the file is UTF-8, and changed it's encoding back and forth between UTF-16 and UTF-8 (tried both with and without BOM) with notepad++, and updated the program to properly reflect this, but no matter what I do, I always get this error. I'm sure I must just be missing something very obvious, but no matter what series of combinations I try this always fails.
First put your content.xml file in res/raw folder then parse it as:
Your xml file res/raw/content.xml :
<?xml version="1.0" encoding="utf-8"?>
<main>
<background>
<defintion>This is a test</defintion>
</background>
</main>
and parse it as:
InputStream is = getResources().openRawResource(R.raw.content);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder;
try {
dBuilder = dbFactory.newDocumentBuilder();
try {
Document doc = dBuilder.parse(is,"UTF-8");
NodeList nl = doc.getElementsByTagName("main");
System.out.println("NodeList NodeList"+nl.getLength());
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //Blows up right here.
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I've encountered the same problem as yours. I finally found the solution:
Never put your xml in res/xml. The xml file will be encoded by android sdk, thus can't be read correctly. However, when you put it in res/raw, the xml file exported to the app will be intact.

Ignoring DTD when parsing XML

How can I ignore the DTD declaration when parsing file with XOM xml library. My file has the following line :
<?xml version="1.0"?>
<!DOCTYPE BlastOutput PUBLIC "-//NCBI//NCBI BlastOutput/EN" "NCBI_BlastOutput.dtd">
//rest of stuff here
And when I try to build() my document I get a filenotfound exception for the DTD file. I know I don't have this file and I don't care about it, so how can it be removed when using XOM?
Here is a code snippet:
public BlastXMLParser(String filePath) {
Builder b = new Builder(false);
//not a good idea to have exception-throwing code in constructor
try {
_document = b.build(filePath);
} catch (ParsingException ex) {
Logger.getLogger(BlastXMLParser.class.getName()).log(Level.SEVERE,"err", ex);
} catch (IOException ex) {
//
}
private Elements getBlastReads() {
Element root = _document.getRootElement();
Elements rootChildren = root.getChildElements();
for (int i = 0; i < rootChildren.size(); i++) {
Element child = rootChildren.get(i);
if (child.getLocalName().equals("BlastOutput_iterations")) {
return child.getChildElements();
}
}
return null;
}
}
I get a NullPointerException at this line:
Element root = _document.getRootElement();
With the DTD line removed from the source XML file I can successfully parse it, but this is not an option in the final production system.
The preferred solution would be to implement an EntityResolver that intercepts requests for the DTD and redirects these to an embedded copy. If you
don't have access to the DTD and
are absolutely sure you won't need it (apart from validation it might also declare character entities that are used in the document) and
you are using the Xerces XML Parser implementation
you can disable fetching of DTD by setting the corresponding SAX feature. In XOM this should be possible by passing an XMLReader to the Builder constructor like this:
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
...
XMLReader xmlreader = XMLReaderFactory.createXMLReader();
xmlreader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
Builder builder = new Builder(xmlreader);
If not using XOM but simply JAXP the abovementioned solution just need to be tweaked into
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setAttribute("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(...);
According to their documentation this is the way to parse document without any validation.
try {
Builder parser = new Builder();
Document doc = parser.build("http://www.cafeconleche.org/");
}
catch (ParsingException ex) {
System.err.println("Cafe con Leche is malformed today. How embarrassing!");
}
catch (IOException ex) {
System.err.println("Could not connect to Cafe con Leche. The site may be down.");
}
If you do want to validate XML schema you have to call new Builder(true):
try {
Builder parser = new Builder(true);
Document doc = parser.build("http://www.cafeconleche.org/");
}
catch (ValidityException ex) {
System.err.println("Cafe con Leche is invalid today. (Somewhat embarrassing.)");
}
catch (ParsingException ex) {
System.err.println("Cafe con Leche is malformed today. (How embarrassing!)");
}
catch (IOException ex) {
System.err.println("Could not connect to Cafe con Leche. The site may be down.");
}
Pay attention that now yet another exception can be thrown: ValidityException

Categories

Resources