After doing a GIT rebase, out of nowhere, I started receiving this exception:
by: org.xml.sax.SAXParseException: "The content of elements must consist of well-formed character data or markup"
The Java code simply tries to unmarshall an xml file to a jaxb object. Something like this:
...
FGIXmlValidationEventCollector collector = new FGIXmlValidationEventCollector();
Unmarshaller unmarshaller = null;
try {
unmarshaller = context.createUnmarshaller();
unmarshaller.setSchema(getSchema());
unmarshaller.setEventHandler(collector);
} catch (JAXBException e) {
throw new FGIXmlException(e);
} catch (SAXException e) {
throw new FGIXmlException(e);
}
public Schema getSchema() throws SAXException {
SchemaFactory schemaFactory = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI);
URL schemaLocation = getClass().getResource("/config/xsd/fgi.xsd");
**return schemaFactory.newSchema(schemaLocation); // exception is thrown here!!!**
}
I'm clueless. There was no code change that justifies this. This code has worked for many years. I don't know why after some trivial git pull/rebase I ended up with this behavior. By the way, there's no apparent problem whatsoever with the XML file that I want to unmarshall. It's an UFT-8 xml file. I've even tried changing the encoding but to no avail.
Any ideas?
Thank you
Related
I would like to know if it is possible to disable the [Fatal Error]:1:50: White spaces are required between publicId and systemId. error in my java program.
Im using java built-in DOM parser api to parse an XML document. The xml document is deliberately incorrect because I want to learn how to handle exceptions related to xml parsing. I also want to say that when the xml document is correct, no exception occurs.
I have already tried with the following :
try {
Document doc = documentBuilder.parse(xmlDocument)
} catch (Throwable t){
System.out.println("An error occur when parsing");
}
The code inside the catch block is displayed correctly but the fatal error message is still showing.
If anyone has a solution, I would be delighted, thanks.
The problem is that by default the error handler for the XML parser prints the errors to the output. You can install your own handler to capture or ignore the errors:
class NullErrorHandler implements ErrorHandler {
#Override
public void fatalError(SAXParseException e) {
// do nothing
}
#Override
public void error(SAXParseException e) {
// do nothing
}
#Override
public void warning(SAXParseException e) {
// do nothing
}
}
Use it as follows:
documentBuilder.setErrorHandler(new NullErrorHandler());
You could also have an error handler that, for example, stored the exceptions in lists in member variables, so you could access them and examine them after parsing the document.
Here's a fully worked-out example:
import javax.xml.parsers.*;
import org.xml.sax.*;
String xml = """
<?xml version="1.0"?>
<!DOCTYPE whatsupdoc PUBLIC
"http://example.com/bugs""http://example.com/bunny">
""";
InputSource getXmlInput(String xml) {
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xml));
return is;
}
var documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
documentBuilder.parse(getXmlInput(xml)); // prints the error and throws
documentBuilder.setErrorHandler(new NullErrorHandler());
documentBuilder.parse(getXmlInput(xml)); // only throws, does not print
Background: I am trying to parse XML into object using JAXB unmarshaller.
What I've done: I used JAXB itself to generate object classes and wrote some methods to unmarshal xml.
public void xmlParser() {
try {
Acquirer acquirer = (Acquirer) readXml(Constants.XML_PATH);
System.out.println(acquirer.getDate());
} catch (JAXBException | IOException e) {
e.printStackTrace();
}
}
/**
* Initializes of JAXB Context and Unmarshaller.
*/
private static void createContext() {
try {
jaxbContext = JAXBContext.newInstance("com.test.xml.generated");
unmarshaller = jaxbContext.createUnmarshaller();
} catch (JAXBException e) {
e.printStackTrace();
}
}
/**
* This reads the XML file from the resources in ClassPath.
*
* #param xmlFile XML file name as String with relative ClassPath
* #return Unmarashalled XML file
* #throws JAXBException
* #throws IOException
* #throws Exception
*/
public Object readXml(String xmlFile) throws JAXBException, IOException {
if (jaxbContext == null) {
createContext();
}
InputStream stream = getClass().getClassLoader().getResourceAsStream(xmlFile);
BufferedInputStream buffredStream = new BufferedInputStream(stream);
***Error:***
Object obj = unmarshaller.unmarshal(buffredStream);
buffredStream.close();
stream.close();
return obj;
}
Error is in Object obj.....
Exception:
javax.xml.bind.UnmarshalException - with linked exception:
[java.io.IOException: Stream closed]
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:246)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:125)
What I've managed to search: I used xml validator to validate xml and it seems fine. I also saw that someone suggested not to use InputStream and etc.. So I tried using File file = new File(); nothing. Moreover I tried to check auto generated object classes, but didn't find anything suspicious. #XmlElement and Root seems to be defined just fine.
P.S. I have xsd scheme of this xml (I generated all object classes using this xsd). I even used online tools to validate them both and everything seems right.
Constants.XML_PATH = "/Acquirer.xml";
Simply change:
InputStream stream = getClass().getClassLoader().getResourceAsStream(xmlFile);
on:
InputStream stream = getClass().getResourceAsStream(xmlFile);
Because when you use getClass().getClassLoader().getResourceAsStream(xmlFile) then it returns null (does not find the resource) and BufferedInputStream then throws the IOException when providing null instead of input stream instance into constructor.
First of all I would like to add that I probably have tried every proposed solution on SO about this issue but still cant get it working.
So this is my problem...
I have an application for parsing XML files. I select an xml file (source) and I validate it against an xsd (this is the file inside my JAR that I cant access). Running the code from within my IDE works fine:
xsd = new File(getClass().getResourceAsStream("xsds/2014/schema.xsd").getFile());
System.out.println(xsd.getAbsolutePath());
//returns: C:\Users\xxx\Desktop\Documents\NetBeansProjects\JavaXMLValidator\build\classes\app\xsds\2014\schema.xsd
But when I build by application to JAR file and I run it I cant get the reference to that file.
When I run the application from within my JAR i get this:
//returns: C:\Users\xxx\Desktop\Documents\NetBeansProjects\JavaXMLValidator\dist\file:C:\Users\xxx\Desktop\Documents\NetBeansProjects\JavaXMLValidator\dist\JavaXMLValidator.jar!\app\xsds\2014\schema.xsd
The path looks ok (i think) but I cant get a correct reference to my file in the code:
Source schemaFile = new StreamSource(xsd);
Schema schema = null;
try {
schema = factory.newSchema(schemaFile);
} catch (SAXException ex) {
JOptionPane.showMessageDialog(null, "Invalid XML Schema Selected!!!\n Exception: "+this.getStackTraceString(ex," "));
return;
}
I get the exception:
SAXParseException: schema_reference.4: Failed to read schema document
'C:\Users\xxx\Desktop\Documents\NetBeansProjects\JavaXMLValidator\dist\file:C:\Users\xxx\Desktop\Documents\NetBeansProjects\JavaXMLValidator\dist\JavaXMLValidator.jar!\app\xsds\2014\schema.xsd',
because 1)could not find the document;
2)the document could not be read;
3)the root element of the document is not <xsd:schema>
........
Can anyone suggest a way that I could have a correct reference to the xsd file withing the JAR?
Thanks a lot for any help
As MadProgrammer says, use the URL:
URL xsd = getClass().getResource("xsds/2014/schema.xsd");
Schema schema = null;
try {
schema = factory.newSchema(xsd);
} catch (SAXException ex) {
JOptionPane.showMessageDialog(null, "Invalid XML Schema Selected!!!\n Exception: "+this.getStackTraceString(ex," "));
return;
}
For example there is a project with such structure:
testproject
xsdfolder
schema.xsd
javaclassfolder
SomeClass.java
public static class SomeClass {
public static URL getLocalXsd() throws MalformedURLException {
URL baseUrl = SomeClass.class.getResource(SomeClass.class.getSimpleName() + ".class");
return new URL(baseUrl, "../xsdfolder/schema.xsd");
}
}
I have an XML schema file in /src/main/resources/vast_2.0.1.xsd.
I need to load it and use it to validate my XML file.
This is what's happening:
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
File schemaFile = new File("/src/main/resources/vast_2.0.1.xsd");
try {
Schema schema = scehmaFactory.newSchema(schemaFile);
Validator validator = schema.newValidator();
Source sourceXMLFile = new StreamSource(validationRequest.xmlInputStream);
validator.validate(sourceXMLFile);
} catch (SAXException e) {
responseEngine.addFailedCheck("NON_VAST_COMPLIANT", "Does not meet VAST 2.0 XML schema specifications");
} catch (IOException e) {
// should not reach here
}
For some reason, after the File schemaFile = new File... line, it ceases to run (using print statements). Am I loading the file incorrectly?
I assume from your directory structure that you are using maven. In maven project, src/main/resources is always in the classpath so you need to specify just the file name without the path. Try this:
File schemaFile = new File("vast_2.0.1.xsd");
I'm creating an XML file using JAXB as follows.
public final class Main
{
private File file;
private transient JAXBContext jaxb;
List<Fruit>fruits;
private void test()
{
try {
jaxb=JAXBContext.newInstance(Fruits.class);
file=new File(System.getenv("UPLOAD_LOCATION")+"\\xml_files\\fruits.xml");
Marshaller marshaller = jaxb.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.FALSE);
if(!file.exists()) {
file.createNewFile();
marshaller.marshal(new Fruits(new ArrayList<Fruit>()), file);
}
else {
fruits=((Fruits) jaxb.createUnmarshaller().unmarshal(file)).getList();
}
for(Fruit fruit:fruits) {
System.out.println(fruit.getId()+" : "+fruit.getName()+" : "+fruit.getPrice());
}
} catch (JAXBException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}/*catch (SAXParseException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}*/
}
public static void main(String... args) {
new Main().test();
}
}
The code that adds objects is excluded. It however generates an XML file something like the following.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<fruits>
<fruit id="1">
<name>Mango</name>
<price>100</price>
</fruit>
<fruit id="2">
<name>Banana</name>
<price>50</price>
</fruit>
<fruit id="3">
<name>Pineapple</name>
<price>80</price>
</fruit>
</fruits>
If this XML file is invalidated for certain reasons, like it may be modified externally.
If this file contains some mulformed XML format then, it throws org.xml.sax.SAXParseException. If this exception is thrown then, I want to recreate this file. Otherwise, the exception will be thrown continually unless the XML contents is manually modified and restructured. For this to be so, this exception should be caught.
The compiler refuses to catch this exception. If an additional catch block for this exception is attempted as shown in the code snipped then, it complains,
exception org.xml.sax.SAXParseException is never thrown in body of
corresponding try statement
How to handle this exception so that the file can be recreated (deleting the old one) in case, this exception is thrown?
I'm not showing the classes (Fruit and Fruits) that create XML elements, since they are not quite related to this question.
SAXParseException is a checked exception and is not declared on the method unmarshal(), so it's normal that you cannot catch it.
There is another exception that you could catch, which is javax.xml.bind.UnmarshalException. this exception extends javax.xml.bind.JAXBException so you have to put your catch block before JAXBException.
In the documentation of the method unmarshal() it says that UnmarshalException is thrown, if a validation error occurs or the Unmarshaller is unable to perform the XML to Java binding.
Note: I verified in the implementation of the Unmarshaller and when an
org.xml.sax.SAXException occurs, it is wrapped in a javax.xml.bind.UnmarshalException.