xstream to parse xml to java object with xml namespace - java

Hi I need to parse xml to object. I am trying to xstream with stax as my xml has namespace. I am getting error because of xsi:schemalocation.
Can anyone help how to configure schemalocation xsi?
I am getting below error:
Message: http://www.w3.org/TR/1999/REC-xml-names-19990114#AttributePrefixUnbound?n:contactDelData&xsi:schemaLocation&xsi
ContactDelData.java
public class ContactDelData {
private String contactId;
private String roid;
private String schemaLocation;
}
ContactDelParser.java
import javax.xml.namespace.QName;
import javax.xml.stream.XMLInputFactory;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.QNameMap;
import com.thoughtworks.xstream.io.xml.StaxDriver;
public class ContactDelParser {
public static void main(String[] args){
String xmlString = "<n:contactDelData
xmlns:n=\"http://www.nominet.org.uk/epp/xml/std-notifications-1.2\"
xsi:schemaLocation=\"http://www.nominet.org.uk/epp/xml/std-notifications-1.2 std-notifications-1.2.xsd\"><n:contactId> EPP-AB2345</n:contactId>
<n:roid>1002703-UK </n:roid></n:contactDelData>";
String namespaceURI="http://www.nominet.org.uk/epp/xml/std-notifications-1.2 std-notifications-1.2.xsd";
String alias="n";
String mappingObjName="contactDelData";
Class response=ContactDelData.class;
QNameMap qmap = new QNameMap();
QName qname = new QName(namespaceURI, "alias", alias);
qmap.registerMapping(qname, AbuseFeedInfoData.class);
StaxDriver staxDriver = new StaxDriver(qmap);
XStream xstream2 = new XStream(staxDriver);
xstream2.alias(mappingObjName, response);
//xstream2.useAttributeFor(response, "xmlns");
//xstream2.aliasAttribute("xsi:schemaLocation", "schemaLocation");
staxDriver.getInputFactory().setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
try {
Object poll = xstream2.fromXML(xmlString);
System.out.println(poll.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}

Related

How to Validate a xml file with catalogs using Xerces2-j

I'm trying to validate an xml file using oasis catalog. What i need is to give the path of the xml file and the path of the catalog that contains the xsd as input and to get the validation (true or error message) as output.
What i have done so far is :
File schemaFile = new File("personal.xsd"); // etc.
Source xmlFile = new StreamSource(new File("personal.xml"));
SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/XML/XMLSchema/v1.1"); // we need to validate with v1.1
try {
Schema schema = schemaFactory.newSchema(schemaFile);
Validator validator = schema.newValidator();
validator.validate(xmlFile);
System.out.println(xmlFile.getSystemId() + " is valid");
} catch (SAXException e) {
System.out.println(xmlFile.getSystemId() + " is NOT valid reason:" + e);
} catch (IOException e) {
e.printStackTrace();
}
So it's working so far.
The issue is to add the catalog. I found some code sample but it is not working :
Source xmlFile = new StreamSource(new File("personal.xml"));
String [] catalogs = {"file:///catalog.xml"};
SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/XML/XMLSchema/v1.1");
try {
XMLCatalogResolver resolver = new XMLCatalogResolver();
resolver.setPreferPublic(true);
resolver.setCatalogList(catalogs);
schemaFactory.setResourceResolver(resolver);
Schema schema = schemaFactory.newSchema();
Validator validator = schema.newValidator();
validator.validate(xmlFile);
}
In the end, the xsd is not find and the validation fails.
Can someone explain me what i am doing wrong ? i feel like it should be simple but i'm missing something.
Thank.
After 2 weeks of research here my conclusion
I never managed to do it with Xerces-2j.
You can do it with the xerces in the JRE (javaSE-1.8), here is how you can do it.
import java.io.File;
import java.io.StringWriter;
import java.net.URL;
//import javax.xml.validation.SchemaFactory;
import java.net.URI;
import java.net.URISyntaxException;
import javax.xml.XMLConstants;
//import javax.xml.catalog.CatalogFeatures;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Schema;
import javax.xml.validation.Validator;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
public class Foo
{
private static int errorCount = 0;
public static void main(String[] args)
{
final String catalogFile = "javax.xml.catalog.files";//CatalogFeatures.Feature.FILES.getPropertyName();
final String catalogPath = "catalog.xml";
final ClassLoader classLoader = Foo.class.getClassLoader();
try
{
final URL catalogUrl = classLoader.getResource(catalogPath);
final URI catalog = catalogUrl.toURI();
if (catalog != null)
{
System.out.println("catalog : "+ catalogFile);
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
// SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/XML/XMLSchema/v1.1");
Schema schema = schemaFactory.newSchema();
StreamSource source = new StreamSource(new File("personal.xml"));
Validator validator = schema.newValidator();
validator.setProperty(catalogFile, catalog.toString());
validator.setErrorHandler(new MyErrorHandler());
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
validator.validate(source, result);
System.out.println(writer);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
private static class MyErrorHandler implements ErrorHandler {
public void warning(SAXParseException e) throws SAXException {
System.out.println("Warning: ");
printException(e);
}
public void error(SAXParseException e) throws SAXException {
System.out.println("Error: ");
printException(e);
}
public void fatalError(SAXParseException e) throws SAXException {
System.out.println("Fattal error: ");
printException(e);
}
private void printException(SAXParseException e) {
errorCount++;
System.out.println(" Line number: "+e.getLineNumber());
System.out.println(" Column number: "+e.getColumnNumber());
System.out.println(" Message: "+e.getMessage());
System.out.println();
}
}
}
GL if you want to use xerces-2J

Parser to read multiple xml file with same XSD and XSLT

I want to read the data from multiple XML files based on the XSD document and the structure of one XML file will not be the same as to another but will follow the xsd schema. Also, the xmls are nested xmls.Can someone help me with it so that I can use the already created utility and add the attributes to it? I need a XML parser which parses each xml file(They are different) based on the xsd schema and returns me a list of the map so that the data can be matched with the DB data.
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
public class Test {
public static void main(String[] args) {
Customer customer = new Customer();
try {
File file = new File("SalesPoslog20200225104558676.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
// output pretty printed
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(customer, file);
jaxbMarshaller.marshal(customer, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Customer {
int organizationID;
int retailStoreID;
int workstationID;
int tillID;
int sequenceNumber;
public int organizationID() {
return organizationID;
}
#XmlElement
public void RetailStoreID(int retailStoreID) {
this.retailStoreID = retailStoreID;
}
public int workstationID() {
return workstationID;
}
#XmlAttribute
public void RetailStoreId(int RetailStoreId) {
this.retailStoreID = retailStoreID;
}
}

Reading XSD from URL using Java

Objective : I want to read a WSDL and print the services in the WSDL, complex types and Complex type definitions.
Worked : I've used WSDL4J for reading WSDL and successfully able to print the services and their parameters (complex types). Now I want to read the complex type definitions which is available in XSD. I'm unable to read XSD .Is ther any way to do it ?
I'm getting XSModel as null
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.wsdl.BindingOperation;
import javax.wsdl.Definition;
import javax.wsdl.WSDLException;
import javax.wsdl.xml.WSDLReader;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import com.ibm.wsdl.BindingImpl;
import com.ibm.wsdl.xml.WSDLReaderImpl;
import com.sun.org.apache.xerces.internal.impl.xs.XSImplementationImpl;
import com.sun.org.apache.xerces.internal.xs.XSLoader;
import com.sun.org.apache.xerces.internal.xs.XSModel;
public class WSDLDetails {
public static void main(String[] args) {
try {
String wsdlURL = "https://abc.xyz.com/webservice/MessagingSevice?WSDL";
String xsdURL = "https://abc.xyz.com/webservice/MessagingSevice?xsd=1";
java.lang.System.setProperty("https.protocols", "TLSv1.2");
getAllBindingOperation(wsdlURL);
readXSD(xsdURL);
} catch (Exception e) {
e.printStackTrace();
}
}
public static List<String> getAllBindingOperation(String wsdlUrl) {
List<BindingOperation> operationList = new ArrayList();
List<String> nameList = new ArrayList();
try {
WSDLReader reader = new WSDLReaderImpl();
reader.setFeature("javax.wsdl.verbose", false);
Definition definition = reader.readWSDL(wsdlUrl.toString());
Map<String, BindingImpl> defMap = definition.getAllBindings();
Collection<BindingImpl> collection = defMap.values();
for (BindingImpl binding : collection) {
operationList.addAll(binding.getBindingOperations());
}
for (BindingOperation operation:operationList) {
nameList.add(operation.getName());
System.out.println("Name :: " + operation.getName());
System.out.println("Request :: " + operation.getBindingInput());
System.out.println("Response :: " + operation.getBindingOutput());
}
} catch (WSDLException e) {
System.out.println("get wsdl operation fail.");
e.printStackTrace();
}
return nameList;
}
public static void readXSD(String xsdURL) {
try {
System.setProperty(DOMImplementationRegistry.PROPERTY, "com.sun.org.apache.xerces.internal.dom.DOMXSImplementationSourceImpl");
DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
com.sun.org.apache.xerces.internal.impl.xs.XSImplementationImpl impl = (XSImplementationImpl) registry.getDOMImplementation("XS-Loader");
XSLoader schemaLoader = impl.createXSLoader(null);
XSModel model = schemaLoader.loadURI(xsdURL);
System.out.println(model);
} catch (Exception e) {
e.printStackTrace();
}
}
You can use xsd2java plugin with maven
https://github.com/qaware/xsd2java-gradle-plugin
Here is an example showing how to retrieve the XSModel from an XSD URL, and print the complex types declared therein.
import org.apache.xerces.impl.xs.XMLSchemaLoader;
import org.apache.xerces.impl.xs.XSComplexTypeDecl;
import org.apache.xerces.impl.xs.XSElementDecl;
import org.apache.xerces.xs.XSConstants;
import org.apache.xerces.xs.XSModel;
import org.apache.xerces.xs.XSNamedMap;
import org.apache.xerces.xs.XSTypeDefinition;
public class Test {
public static void main(String[] args) {
try {
String xsdURL = "http://fsharp.github.io/FSharp.Data/data/po.xsd";
XMLSchemaLoader xsLoader = new XMLSchemaLoader();
XSModel xsModel = xsLoader.loadURI(xsdURL);
// print global element declarations
System.out.println("\nGlobal Element Declarations:");
XSNamedMap globalElemDecls = xsModel.getComponents(XSConstants.ELEMENT_DECLARATION);
globalElemDecls.forEach((k,v) -> System.out.println((XSElementDecl) v));
// print global complex type declarations
System.out.println("\nGlobal Complex Type Declarations:");
XSNamedMap globalComplexTypeDecls = xsModel.getComponents(XSTypeDefinition.COMPLEX_TYPE);
globalComplexTypeDecls.forEach((k,v) -> System.out.println((XSComplexTypeDecl) v));
} catch (Exception e) {
e.printStackTrace();
}
}
}
If you got null at xsLoader.loadURI(xsdURL), it is likely there are some flaws in the given XSD file. For example, "White spaces are required between publicId and systemId". You might need to fix these flaws first.

Get particular object in xml based on supplied criteria

I am new born for Jaxb and trying to do read/write operation in xml.
I am done with the write operation but having trouble with the read one.
I have the following xml-
<docOperations>
<SkuSlabs id="1">
<docId>677-WORK</docId>
<itemIds>11</itemIds>
<itemName>new item addedaaaaaa</itemName>
</SkuSlabs>
<SkuSlabs id="2">
<docId>699-WORK</docId>
<itemIds>21</itemIds>
<itemName>extra</itemName>
</SkuSlabs>
</docOperations>
Now i want to unmarshal the SkuSlabs object based on the condition supplied 'where id = 1', but don't know how to achieve that.
Please help.
Here you are (as you want add same access modifiers to attributes):
package pl.skuslab;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "SkuSlabs")
#XmlAccessorType(XmlAccessType.FIELD)
public class SkusLab {
#XmlAttribute
int id;
String docId;
int itemIds;
String itemName;
public SkusLab(int id, String docId, int itemIds, String itemName) {
super();
this.id = id;
this.docId = docId;
this.itemIds = itemIds;
this.itemName = itemName;
}
public SkusLab() {
super();
}
#Override
public String toString() {
return "SkusLab [id=" + id + ", docId=" + docId + ", itemIds=" + itemIds + ", itemName=" + itemName + "]";
}
}
Class DocOperation:
package pl.skuslab;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class DocOperation {
#XmlElement(name = "SkuSlabs")
List<SkusLab> docOperations = new ArrayList<SkusLab>();
}
Class with the main function. Firstly I generate XML like you wrote in question, then I unmarshall xml to obejcts. First obejct is printed.
package pl.skuslab;
import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
public class SkusLabJaxb {
private static JAXBContext jc;
static {
try {
jc = JAXBContext.newInstance(DocOperation.class);
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
private static Marshaller getMarshaller() {
try {
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.FALSE);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
return marshaller;
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
private static Unmarshaller getUnmarshaller() {
try {
Unmarshaller unmarshaller = jc.createUnmarshaller();
return unmarshaller;
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
String xml = "";
try {
DocOperation doper = new DocOperation();
doper.docOperations.add(new SkusLab(1, "677-WORK", 11, "new item addedaaaaaa"));
doper.docOperations.add(new SkusLab(2, "699-WORK", 21, "extra"));
StringWriter sw = new StringWriter();
getMarshaller().marshal(doper, sw);
xml = sw.toString();
System.out.println(xml);
} catch (JAXBException e) {
e.printStackTrace();
}
try {
DocOperation docOperation = (DocOperation) getUnmarshaller().unmarshal(
new StringReader(xml));
System.out.println(docOperation.docOperations.get(0).toString());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

kryo serializing of class (task object) in apache spark returns null while de-serialization

I am using java spark API to write some test application . I am using a class which doesn't extends serializable interface . So to make the application work I am using kryo serializer to serialize the class . But the problem which I observed while debugging was that during the de-serialization the returned class object becomes null and in turn throws a null pointer exception . It seems to be closure problem where things are going wrong but not sure.Since I am new to this kind of serialization I don't know where to start digging.
Here is the code I am testing :
package org.apache.spark.examples;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
/**
* Spark application to test the Serialization issue in spark
*/
public class Test {
static PrintWriter outputFileWriter;
static FileWriter file;
static JavaSparkContext ssc;
public static void main(String[] args) {
String inputFile = "/home/incubator-spark/examples/src/main/scala/org/apache/spark/examples/InputFile.txt";
String master = "local";
String jobName = "TestSerialization";
String sparkHome = "/home/test/Spark_Installation/spark-0.7.0";
String sparkJar = "/home/test/TestSerializationIssesInSpark/TestSparkSerIssueApp/target/TestSparkSerIssueApp-0.0.1-SNAPSHOT.jar";
SparkConf conf = new SparkConf();
conf.set("spark.closure.serializer","org.apache.spark.serializer.KryoSerializer");
conf.set("spark.kryo.registrator", "org.apache.spark.examples.MyRegistrator");
// create the Spark context
if(master.equals("local")){
ssc = new JavaSparkContext("local", jobName,conf);
//ssc = new JavaSparkContext("local", jobName);
} else {
ssc = new JavaSparkContext(master, jobName, sparkHome, sparkJar);
}
JavaRDD<String> testData = ssc.textFile(inputFile).cache();
final NotSerializableJavaClass notSerializableTestObject= new NotSerializableJavaClass("Hi ");
#SuppressWarnings({ "serial", "unchecked"})
JavaRDD<String> classificationResults = testData.map(
new Function<String, String>() {
#Override
public String call(String inputRecord) throws Exception {
if(!inputRecord.isEmpty()) {
//String[] pointDimensions = inputRecord.split(",");
String result = "";
try {
FileWriter file = new FileWriter("/home/test/TestSerializationIssesInSpark/results/test_result_" + (int) (Math.random() * 100));
PrintWriter outputFile = new PrintWriter(file);
InetAddress ip;
ip = InetAddress.getLocalHost();
outputFile.println("IP of the server: " + ip);
result = notSerializableTestObject.testMethod(inputRecord);
outputFile.println("Result: " + result);
outputFile.flush();
outputFile.close();
file.close();
} catch (UnknownHostException e) {
e.printStackTrace();
}
catch (IOException e1) {
e1.printStackTrace();
}
return result;
} else {
System.out.println("End of elements in the stream.");
String result = "End of elements in the input data";
return result;
}
}
}).cache();
long processedRecords = classificationResults.count();
ssc.stop();
System.out.println("sssssssssss"+processedRecords);
}
}
Here is the KryoRegistrator class
package org.apache.spark.examples;
import org.apache.spark.serializer.KryoRegistrator;
import com.esotericsoftware.kryo.Kryo;
public class MyRegistrator implements KryoRegistrator {
public void registerClasses(Kryo kryo) {
kryo.register(NotSerializableJavaClass.class);
}
}
Here is the class I am serializing :
package org.apache.spark.examples;
public class NotSerializableJavaClass {
public String testVariable;
public NotSerializableJavaClass(String testVariable) {
super();
this.testVariable = testVariable;
}
public String testMethod(String vartoAppend){
return this.testVariable + vartoAppend;
}
}
This is because spark.closure.serializer only supports the Java serializer. See http://spark.apache.org/docs/latest/configuration.html about spark.closure.serializer

Categories

Resources