Different parent child namespace prefix expected - java

I have two xsds from which i have generated jaxb pojos using xjc. And i have generated XMLs using jaxb marshaller with jaxb-impl-2.2.6
For this I have overriden NamespacePrefixMapper as MyNamespacePrefixMapper
Parent.xsd
<xs:schema targetNamespace="parent"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:Env="Parent"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:child="urn:xsd:child">
<xs:import namespace="urn:xsd:child" schemaLocation="child.xsd"/>
<xs:element name="parent">
<xs:complexType>
<xs:sequence>
<xs:element name="child" type="child:child1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
child.xsd
<xs:schema xmlns="urn:xsd:child" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:xsd:child">
<xs:element name="child" type="child1"/>
<xs:complexType name="child1">
<xs:sequence>
<xs:element name="Id" type="Max20Text"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="Max20Text">
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="20"/>
</xs:restriction>
</xs:simpleType>
XmlMarshallingTest.java
import javax.xml.bind.*;
import javax.xml.stream.XMLStreamException;
import org.junit.Test;
import parent.Parent;
import xsd.child.Child1;
public class XmlMarshallingTest {
#Test
public void testXmlMarshalling() throws JAXBException, XMLStreamException{
Parent envelope = new Parent();
Child1 businessApplicationHeaderV01 = new Child1();
businessApplicationHeaderV01.setId("ABC123");
envelope.setChild(businessApplicationHeaderV01);
JAXBContext context = JAXBContext.newInstance(envelope.getClass());
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new MyNamespacePrefixMapper());
marshaller.marshal(envelope, System.out);
}
}
MyNamespacePrefixMapper.java
import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
public class MyNamespacePrefixMapper extends NamespacePrefixMapper {
#Override
public String getPreferredPrefix(String namespaceUri, String suggestion, boolean arg2) {
if("Parent".equals(namespaceUri)) {
return "parentPrefix";
} else if("urn:xsd:child".equals(namespaceUri)) {
return "childPrefix";
}
return "defaultPrefix";
}
}
the generated xml is like
<parentPrefix:parent xmlns:childPrefix="urn:xsd:child" xmlns:parentPrefix="parent">
<parentPrefix:child>
<childPrefix:Id>ABC123</childPrefix:Id>
</parentPrefix:child>
</parentPrefix:parent>
Here, my problem is , I expect the xml to be look like following
<parentPrefix:parent xmlns:childPrefix="urn:xsd:child" xmlns:parentPrefix="parent">
<childPrefix:child>
<childPrefix:Id>ABC123</childPrefix:Id>
</childPrefix:child>
</parentPrefix:parent>
I expect the prefix of child tag to be "childPrefix" but it shows "parentPrefix"
The parent tag is well generated with prefix "parentPrefix"
Environment Description
Maven 3.0.4
Java version: 1.7.0_04
OS : windows 7

Your schema defines the parent element as having a child element named child in the parent schema's own targetNamespace, whose type happens to come from the child namespace. If you want the parent to use the child element that is defined in the child schema (and thus in the urn:xsd:child namespace) then instead of
<xs:element name="child" type="child:child1"/>
you need
<xs:element ref="child:child"/>

Related

No URI javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"SearchAndList"). Expected elements are (none)

I am having trouble to unmarshall my data. I got the following error:
ERROR FsceClient - Error in getDataInMatches : unexpected element
(uri:"", local:"SearchAndList"). Expected elements are (none)
requested params:+COUNTRY=US+YR=2016+DIV=Ford+WB=122.0
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"SearchAndList"). Expected elements are (none)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:726)
This is my xml file:
<SearchAndList>
<fvd>
+COUNTRY=US+YR=2016+DIV=Ford+WB=122.0
</fvd>
<sol>
<rsi>
<sType>Ss</sType>
<mHave>true</mHave>
<toAr>0</toAr>
<toAr>0</toAr>
<toAr>22</toAr>
</rsi>
<rsi>
<sType>ssa</sType>
<mHave>true</mHave>
<toAr>77</toAr>
</rsi>
</sol>
<sol>
<rsi>
<sType>sve</sType>
<mHave>false</mHave>
<toAr>0</toAr>
<toAr>21</toAr>
</rsi>
</sol>
</SearchAndList>
This is encountered when the XSD schema does not contain element definitions and only contains class definitions (i.e. complex types).
e.g. for this XSD,
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="foo">
<xs:sequence>
<xs:element name="bar" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
The object factory created is like this:
#XmlRegistry
public class ObjectFactory {
public ObjectFactory() {
}
public Foo createFoo() {
return new Foo();
}
}
BUT FOR THIS XSD:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="foo" type="foo" nillable="true"/>
<xs:complexType name="foo">
<xs:sequence>
<xs:element name="bar" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
The ObjectFactory class created by JAXB is:
#XmlRegistry
public class ObjectFactory {
private final static QName _Foo_QNAME = new QName("", "foo");
public ObjectFactory() {
}
public Foo createFoo() {
return new Foo();
}
#XmlElementDecl(namespace = "", name = "foo")
public JAXBElement<Foo> createFoo(Foo value) {
return new JAXBElement<Foo>(_Foo_QNAME, Foo.class, null, value);
}
}
You can see that the JAXBElement wrapper creation method is also added. With the second XSD, the unmarshaller knows what to do when it encounters a tag with name "foo". So if you have an XSD, add "element" definitions as well as the complex types.
----- EDIT----
The sample unmarshaller code:
JAXBContext jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Object result = ((JAXBElement<Object>) jaxbUnmarshaller.unmarshal(stream)).getValue();

XSD:anyType to java Object

I have an xsd as follows:
<xs:complexType name="exampleDataType">
<xs:sequence>
<xs:element name="payload" type="xs:anyType" minOccurs="0"/>
<xs:element name="message" type="tns:message" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
However when I try to get the payload value from java it returns null. Can anyone help me with this?
I have also faced this issue recently, below is the workaround:
XSD:
Java Code:
ClassLoader classLoader = new XmlToObject().getClass().getClassLoader();
File file = new File(classLoader.getResource("myXmlFile.xml").getFile());
JAXBContext jaxbContext = JAXBContext.newInstance(MyPojo.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
MyPojo myPojo = (MyPojo) jaxbUnmarshaller.unmarshal(file);
Object check = myPojo.getCheck();
if (check instanceof Node) {
ElementNSImpl checkElement = (ElementNSImpl) check;
System.out.println("check=" + checkElement.getTextContent());
}

Writing Rest client to call the RESt service?

I wrote RESt web service using JERSEY. PFB my end point.
Endpoint class:
package org.madbit.rest;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.madbit.rest.ws.SumRequest;
import org.madbit.rest.ws.SumResponse;
#Path("/services")
public class SumEndpoint {
#POST
#Path("sum")
#Produces(MediaType.APPLICATION_XML)
#Consumes(MediaType.APPLICATION_XML)
public SumResponse getSum(SumRequest request) {
SumResponse response = new SumResponse();
List<Integer> elements = request.getElement();
int sum = 0;
for (Integer element: elements)
sum += element;
response.setSum(sum);
return response;
}
}
XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.madbit.org/SumService" xmlns:tns="http://www.madbit.org/SumService" elementFormDefault="qualified">
<xs:element name="SumRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="element" type="xs:int" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="SumResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="sum" type="xs:int" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
I have generated POJOs from above xsd using Maven JAXB plugin. now i have SumRequest and SumResponse POJOs.
Now how can i write a Jersey client to get the response by passing below input?
<?xml version="1.0" encoding="ISO-8859-1"?>
<SumRequest xmlns="http://www.madbit.org/SumService">
<element>1</element>
<element>4</element>
</SumRequest>
Thanks!
This should work for you:
public static void testWS(){
try{
SumRequest sumRequest = new SumRequest(1,4); //here you have to create your input object
Client client = Client.create();
WebResource service = client.resource("http://www.madbit.org/SumService");
/*
* here you are calling the post method with your input object attached
*/
ClientResponse response = service.type(MediaType.APPLICATION_XML).post(ClientResponse.class, sumRequest);
SumResponse res = response.getEntity(SumResponse.class);
System.out.println("output JaxbWS:\n " + res.toString());
}
catch(Exception e){
System.out.println(e.getMessage());
}
I must add that your object SumRequest that you are passing will be automatically converted in XML because you method specifies that consumes XML.

Java XML Schema validation: prefix not bound

I have followed this tutorial for validating XML files. But I am receiving exception when validating XML file. What I am doing wrong? My codes:
XML schema:
<?xml version="1.0" encoding="utf-8" ?>
<!-- definition of simple elements -->
<xs:element name="first_name" type="xs:string" />
<xs:element name="last_name" type="xs:string" />
<xs:element name="phone" type="xs:string" />
<!-- definition of attributes -->
<xs:attribute name="type" type="xs:string" use="required"/>
<xs:attribute name="date" type="xs:date" use="required"/>
<!-- definition of complex elements -->
<xs:element name="reporter">
<xs:complexType>
<xs:sequence>
<xs:element ref="first_name" />
<xs:element ref="last_name" />
<xs:element ref="phone" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="report">
<xs:complexType>
<xs:attribute ref="type"/>
<xs:attribute ref="date" />
<xs:sequence>
<xs:element ref="reporter" />
</xs:sequence>
</xs:complexType>
</xs:element>
XML file to validate:
<?xml version="1.0" encoding="utf-8" ?>
<report type="5" date="2012-12-14">
<reporter>
<first_name>FirstName</firstname>
<last_name>Lastname</lastname>
<phone>+xxxxxxxxxxxx</phone>
</reporter>
</report>
Java source for validating:
import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.*;
import org.xml.sax.SAXException;
import java.io.*;
public class ProtocolValidator
{
public static void main(String [] args) throws Exception
{
Source schemaFile = new StreamSource(new File("schema.xsd"));
Source xmlFile = new StreamSource(new File("test_xml.xml"));
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(schemaFile);
Validator validator = schema.newValidator();
try{
validator.validate(xmlFile);
System.out.println(xmlFile.getSystemId() + " is valid");
}
catch (SAXException e)
{
System.out.println(xmlFile.getSystemId() + " is NOT valid");
System.out.println("Reason: " + e.getLocalizedMessage());
}
}
}
Exception I am receiving:
Exception in thread "main" org.xml.sax.SAXParseException; systemId: file:/root/test/schema.xsd; lineNumber: 4; columnNumber: 50; The prefix "xs" for element "xs:element" is not bound.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:198)...
The XML schema file itself needs to be a valid XML document. You are missing the outer schema element and the namespace declaration for the xs prefix.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- schema elements here -->
</xs:schema>
Add this line to your schema, just below the first line:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
... and a closing tag as the last line in the schema:
</xs:schema>

XML validation against xsd's in Java

Issue:
We have several services that generate a fair amount of XML via XSLT. We don't have any XSD's. I have taken the time to create the XSD's and want to confirm they are correct. Currently I am attempting to verify that the XSD and the XML are validate correctly.
Problem:
I have an xsd(common.xsd) that is imported into all the xsd's. It is not publicly hosted yet, so only recently I found putting the full path of the common.xsd in the AccountList.xsd I was able to get further. I am now receiving the following:
org.xml.sax.SAXParseException; lineNumber: 9; columnNumber: 70; s4s-att-invalid-value: Invalid attribute value for 'type' in element 'element'. Recorded reason: UndeclaredPrefix: Cannot resolve 'common:response' as a QName: the prefix 'common' is not declared.
I am at a loss. I cannot find an example that has been asked in forums or a source code snippet that gets a success. I'd appreciate any assistance in getting this to successfully validate my xml.
common.xsd
<xs:schema version="1.0" elementFormDefault="qualified" attributeFormDefault="unqualified"
xmlns="http://www.myorg.com/xsd/gen_fin"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.myorg.com/xsd/gen_fin">
<xs:complexType name="response">
<xs:sequence>
<xs:element name="code" type="xs:string"/>
<xs:element name="description" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
AccountList.xsd
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema version="1.0" elementFormDefault="qualified" attributeFormDefault="unqualified"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://www.myorg.com/xsd/accList"
targetNamespace="http://www.myorg.com/xsd/accList"
xmlns:common="http://www.myorg.com/xsd/gen_fin">
<xs:import namespace="http://www.myorg.com/xsd/gen_fin"
schemaLocation="/home/me/dev/projects/svn/myorg/xsd/src/main/resources/bg/gen_resp/common.xsd"/>
<xs:element name="fundamo">
<xs:complexType>
<xs:sequence>
<xs:element name="response" type="common:response" minOccurs="1" maxOccurs="1"/>
<xs:element name="transaction" type="tns:transaction" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="transaction">
<xs:sequence>
<xs:element name="transactionRef" type="xs:string"/>
<xs:element name="dateTime" type="xs:string"/>
<xs:element name="userName" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Test.java
final InputStream commonXsdStream = getXsd(BG_GEN_RESP_XSD_PATH, COMMON);
ClassPathResource fullXsdListing = new ClassPathResource(BG_GEN_RESP_XSD_PATH);
File[] allXsds = fullXsdListing.getFile().listFiles();
for (File currentXsd : allXsds) {
final int filenameLength = currentXsd.getName().length();
final String filenameSanExt = currentXsd.getName().substring(0, filenameLength - 4);
if (!IGNORE.contains(filenameSanExt)) {
final InputStream xsltStream = getXslt(BG_GEN_RESP_XSLT_PATH, filenameSanExt);
final InputStream xsdStream = getXsd(BG_GEN_RESP_XSD_PATH, filenameSanExt);
TransformerFactory xmlTransformer = TransformerFactory.newInstance();
Templates xsltTemplate = xmlTransformer.newTemplates(new StreamSource(xsltStream));
final XSLToXMLConvertor converter = new XSLToXMLConvertor();
String generatedXml = converter.getXML(inputData, xsltTemplate);
LOG.info(generatedXml);
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(lnew StreamSource(xsdStream));
Validator validator = schema.newValidator();
validator.validate(new StreamSource(new StringReader(generatedXml)));
/*
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
docBuilderFactory.setNamespaceAware(true);
docBuilderFactory.setValidating(true);
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
docBuilder.parse(new InputSource(new ByteArrayInputStream(generatedXml.getBytes("utf-8"))));
*/
}
}
}
It's usually a good idea to have a namespace and targetNamespace defined, although as Petru Gardea pointed out, not strictly necessary. Here's a combination that absolutely works:
AccountList.xsd
<xs:schema
version="1.0"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://www.myorg.com/xsd/accList"
targetNamespace="http://www.myorg.com/xsd/accList"
xmlns:common="http://www.myorg.com/xsd/gen_fin">
<xs:import namespace="http://www.myorg.com/xsd/gen_fin" schemaLocation="common.xsd" />
<xs:element name="fundamo">
<xs:complexType>
<xs:sequence>
<xs:element name="response" type="common:response"
minOccurs="1" maxOccurs="1" />
<xs:element name="transaction" type="tns:transaction"
minOccurs="0" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="transaction">
<xs:sequence>
<xs:element name="transactionRef" type="xs:string" />
<xs:element name="dateTime" type="xs:string" />
<xs:element name="userName" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
common.xsd
<xs:schema
version="1.0"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
xmlns="http://www.myorg.com/xsd/gen_fin"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.myorg.com/xsd/gen_fin">
<xs:complexType name="response">
<xs:sequence>
<xs:element name="code" type="xs:string" />
<xs:element name="description" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
NewFile.xml (based on that schema):
<tns:fundamo xmlns:p="http://www.myorg.com/xsd/gen_fin"
xmlns:tns="http://www.myorg.com/xsd/accList" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.myorg.com/xsd/accList AccountList.xsd ">
<tns:response>
<p:code>p:code</p:code>
<p:description>p:description</p:description>
</tns:response>
</tns:fundamo>
ValidateXml.java:
import java.io.File;
import java.io.IOException;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
public class ValidateXml {
/**
* #param args
*/
public static void main(String[] args) {
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
DocumentBuilder parser = documentBuilderFactory.newDocumentBuilder();
Document document = parser.parse(new File("NewFile.xml"));
Schema schema = schemaFactory.newSchema(new File("AccountList.xsd"));
Validator validator = schema.newValidator();
validator.validate(new DOMSource(document));
} catch (SAXException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
You error related to "cannot find the declaration of element" is usually related to the XML document not being namespace-aware. Verify that your path to both XSDs is correct, and go back to the block of code where you build an XML document that is namespace-aware.

Categories