I have a XML schema:-
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="unqualified">
<xsd:element name="Person">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:ID" use="required"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="Book">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Title" type="xsd:string"/>
<xsd:element name="Author">
<xsd:complexType>
<xsd:attribute name="idref" type="xsd:IDREF"
use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="root">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="Person" />
<xsd:element ref="Book" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
and corresponding to above XML schema, I have following incoming XML:-
<?xml version="1.0" encoding="utf-8" ?>
<root>
<Person id="P234">
<Name>0002</Name>
</Person>
<Book>
<Title>0001</Title>
<Author idref="P234"/>
</Book>
</root>
I know using XML parser validation, I can validate if above XML conforms to my XML schema.for e.g. id and idref should be present. Now what I want to know is which parser(SAX/DOM/STAX) can fetch me complete XML element based on idref. So basically in above example, once parser reaches idref="P234", it should return me complete <Person>...</Person>. Another query is does any parser support id and idref merging, which can replace content of idref with actual element and return me merged XML.
Parsers don't do it, as I know. Use XSLT to do the magic. Moreover, idrefs could be self-referenced, have a cyclic dependency, so it's impossible just "replace content with actual element".
E.g. say you have the xml:
<?xml version="1.0" encoding="utf-8" ?>
<root>
<Person id="P234">
<Name>0002</Name>
<WroteBook idref="B442"/>
</Person>
<Book id="B442">
<Title>0001</Title>
<Author idref="P234"/>
</Book>
</root>
What would you expect from a parser?
An XSLT (not tested myself however):
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="#idref">
<xsl:apply-templates select="id(.)"/>
</xsl:template>
</xsl:stylesheet>
Related
I have a requirement in SOA/XSLT to get the batch elements record in a single element using XSLT, below are the input file and applied XSLT details. please help me out to get as expected format.
Source File-:
<?xml version="1.0" encoding="windows-1252" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.example.org"
targetNamespace="http://www.example.org" elementFormDefault="qualified">
<xsd:element name="Receive1_Read_InputVariable">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="part">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Root-Element">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Test" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="C1" type="xsd:integer"/>
<xsd:element name="C2" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Target File-:
<?xml version="1.0" encoding="windows-1252" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.example.org"
targetNamespace="http://www.example.org" elementFormDefault="qualified">
<xsd:element name="Payment">
<xsd:annotation>
<xsd:documentation>A sample element</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="File" type="xsd:string"/>
<xsd:element name="Batch" minOccurs="1" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="BatchH" minOccurs="1" type="xsd:string"/>
<xsd:element name="Entry" minOccurs="1" type="xsd:string"/>
<xsd:element name="NOC" minOccurs="0" type="xsd:string"/>
<xsd:element name="BatchC" minOccurs="1" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="FileC" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Used XSLT:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:socket="http://www.oracle.com/XSL/Transform/java/oracle.tip.adapter.socket.ProtocolTranslator" xmlns:oracle-xsl-mapper="http://www.oracle.com/xsl/mapper/schemas" xmlns:dvm="http://www.oracle.com/XSL/Transform/java/oracle.tip.dvm.LookupValue" xmlns:mhdr="http://www.oracle.com/XSL/Transform/java/oracle.tip.mediator.service.common.functions.MediatorExtnFunction" xmlns:ns0="http://www.example.org" xmlns:oraxsl="http://www.oracle.com/XSL/Transform/java" xmlns:oraext="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.ExtFunc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xp20="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.Xpath20" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xref="http://www.oracle.com/XSL/Transform/java/oracle.tip.xref.xpath.XRefXPathFunctions" exclude-result-prefixes=" oracle-xsl-mapper xsi xsd xsl ns0 socket dvm mhdr oraxsl oraext xp20 xref"
xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:client="http://xmlns.oracle.com/Test/BPELProcess1"
xmlns:plt="http://schemas.xmlsoap.org/ws/2003/05/partner-link/"
xmlns:tns="http://xmlns.oracle.com/pcbpel/adapter/file/Test/fileReference"
xmlns:jca="http://xmlns.oracle.com/pcbpel/wsdl/jca/">
<oracle-xsl-mapper:schema>
<!--SPECIFICATION OF MAP SOURCES AND TARGETS, DO NOT MODIFY.-->
<oracle-xsl-mapper:mapSources>
<oracle-xsl-mapper:source type="WSDL">
<oracle-xsl-mapper:schema location="../WSDLs/BPELProcess1.wsdl"/>
<oracle-xsl-mapper:rootElement name="Receive1_Read_InputVariable" namespace="http://www.example.org"/>
</oracle-xsl-mapper:source>
</oracle-xsl-mapper:mapSources>
<oracle-xsl-mapper:mapTargets>
<oracle-xsl-mapper:target type="WSDL">
<oracle-xsl-mapper:schema location="../WSDLs/fileReference.wsdl"/>
<oracle-xsl-mapper:rootElement name="Payment" namespace="http://www.example.org"/>
</oracle-xsl-mapper:target>
</oracle-xsl-mapper:mapTargets>
<!--GENERATED BY ORACLE XSL MAPPER 12.2.1.4.0(XSLT Build 190828.0353.3300) AT [TUE JUN 28 14:52:16 IST 2022].-->
</oracle-xsl-mapper:schema>
<!--User Editing allowed BELOW this line - DO NOT DELETE THIS LINE-->
<xsl:template match="/">
<ns0:Payment>
<xsl:if test="/ns0:Receive1_Read_InputVariable/ns0:part/ns0:Root-Element/ns0:Test/ns0:C1 = "1"">
<ns0:FileHeader>
<xsl:value-of select="concat (/ns0:Receive1_Read_InputVariable/ns0:part/ns0:Root-Element/ns0:Test/ns0:C1, /ns0:Receive1_Read_InputVariable/ns0:part/ns0:Root-Element/ns0:Test/ns0:C2 )"/>
</ns0:FileHeader>
</xsl:if>
<xsl:for-each select="/ns0:Receive1_Read_InputVariable/ns0:part/ns0:Root-Element/ns0:Test">
<ns0:Batch>
<xsl:if test="starts-with (/ns0:C1, "5" )">
<ns0:BatchH>
<xsl:value-of select="concat (/ns0:C1, /ns0:C2 )"/>
</ns0:BatchH>
</xsl:if>
<xsl:if test="starts-with (/ns0:C1, "6" )">
<ns0:Entry>
<xsl:value-of select="concat (/ns0:C1, /ns0:C2 )"/>
</ns0:Entry>
</xsl:if>
<xsl:if test="starts-with (/ns0:C1, "7" )">
<ns0:NOC>
<xsl:value-of select="concat (/ns0:C1, /ns0:C2 )"/>
</ns0:NOC>
</xsl:if>
<xsl:if test="starts-with (/ns0:C1, "8" )">
<ns0:BatchC>
<xsl:value-of select="concat (/ns0:C1, /ns0:C2 )"/>
</ns0:BatchC>
</xsl:if>
</ns0:Batch>
</xsl:for-each>
<xsl:if test="starts-with (/ns0:Receive1_Read_InputVariable/ns0:part/ns0:Root-Element/ns0:Test/ns0:C1, "9" )">
<ns0:FileC>
<xsl:value-of select="concat (/ns0:Receive1_Read_InputVariable/ns0:part/ns0:Root-Element/ns0:Test/ns0:C1, /ns0:Receive1_Read_InputVariable/ns0:part/ns0:Root-Element/ns0:Test/ns0:C2 )"/>
</ns0:FileC>
</xsl:if>
</ns0:Payment>
</xsl:template>
</xsl:stylesheet>
Received Output Format-:
<?xml version = '1.0' encoding = 'UTF-8'?>
<ns0:Payment xmlns:jca="http://xmlns.oracle.com/pcbpel/wsdl/jca/" xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://xmlns.oracle.com/pcbpel/adapter/file/Test/fileReference" xmlns:client="http://xmlns.oracle.com/Test/BPELProcess1" xmlns:plt="http://schemas.xmlsoap.org/ws/2003/05/partner-link/" xmlns:ns0="http://www.example.org">
<ns0:File>1012880044418 09100001921101NV </ns0:File>
<ns0:Batch/>
<ns0:Batch>
<ns0:BatchH>5200NV 3880044418WEBSP 211209000017000001</ns0:BatchH>
</ns0:Batch>
<ns0:Batch>
<ns0:Entry>6261224007241234567890123456700100000 1013ONM S 109100001173</ns0:Entry>
</ns0:Batch>
<ns0:Batch>
<ns0:NOC>799R010000576953 12240072 0910000123</ns0:NOC>
</ns0:Batch>
<ns0:Batch>
<ns0:Batch>82000122400720000000175670000000000003418 091000010000001</ns0:Batch>
</ns0:Batch>
<ns0:Batch>
<ns0:Batch>5200NV ENTH SPPCO 3880044418MT 2112090001091000017000002</ns0:Batch>
</ns0:Batch>
<ns0:Batch>
<ns0:Entry>626122400724123456789012345670000033OR R 1091000012072183</ns0:Entry>
</ns0:Batch>
<ns0:Batch>
<ns0:NOC>799R010007 12242 091000012072183</ns0:NOC>
</ns0:Batch>
<ns0:Batch>
<ns0:BatchC>82002400720000000162820000000000003880044418 091000010000002</ns0:BatchC>
</ns0:Batch>
<ns0:Batch/>
</ns0:Payment>
Required Format-:
<?xml version = '1.0' encoding = 'UTF-8'?>
<ns0:Payment xmlns:jca="http://xmlns.oracle.com/pcbpel/wsdl/jca/" xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://xmlns.oracle.com/pcbpel/adapter/file/Test/fileReference" xmlns:client="http://xmlns.oracle.com/Test/BPELProcess1" xmlns:plt="http://schemas.xmlsoap.org/ws/2003/05/partner-link/" xmlns:ns0="http://www.example.org">
<ns0:File>10128800112130344A094101NV </ns0:File>
<ns0:Batch>
<ns0:BatchH>5200NV 38800EBSPC 211209000109000001</ns0:BatchH>
<ns0:Entry>62612240072412345678901270010SONM S 1091000012072173</ns0:Entry>
<ns0:NOC>799R010000019635 12240072 091000012072173</ns0:NOC>
<ns0:BatchC>82000000020012240072000000017567000018 091000010000001</ns0:BatchC>
</ns0:Batch>
<ns0:Batch>
<ns0:BatchH>5200NV 38800WPPC 2112090001091000017000002</ns0:Batch>
<ns0:Entry>62612240074567000001628200200000 10203NOR R 1091002183</ns0:Entry>
<ns0:NOC>799R01000001 12240 091000012072183</ns0:NOC>
<ns0:BatchC>8200000002001224020000000000003880044418 091000010000002</ns0:BatchC>
</ns0:Batch>
<ns0:Batch/>
</ns0:Payment>
Added -----Input file
<?xml version="1.0" encoding="UTF-8" ?>
<Receive1_Read_InputVariable xmlns="http://www.example.org">
<part name="name1">
<Root-Element>
<Test>
<C1>1</C1>
<C2>012880044418 0910000192112130344A0941 </C2>
</Test>
<Test>
<C1>5</C1>
<C2>200NV 3880044418WEBSPPC PYMT 2112090001091000017000001</C2>
</Test>
<Test>
<C1>6</C1>
<C2>2612240072412345678901234567000001756700100000 1013NM S 1091000012072173</C2>
</Test>
<Test>
<C1>7</C1>
<C2>99R01000001963 12240072 091000012072173</C2>
</Test>
<Test>
<C1>8</C1>
<C2>200000002001224007200000000003880044418 091000010000001</C2>
</Test>
<Test>
<C1>5</C1>
<C2>200NV 3880044418 2112090001091000017000002</C2>
</Test>
<Test>
<C1>6</C1>
<C2>2612240072412345678901234567000001628200200000 10 00012072183</C2>
</Test>
<Test>
<C1>7</C1>
<C2>99R01000001963577647 12240072 091000012072183</C2>
</Test>
<Test>
<C1>8</C1>
<C2>20000000200122400720000000162820000000000003880044418 091000010000002</C2>
</Test>
<Test>
<C1>9</C1>
<C2>000054000022000050648000000716319000000000000 </C2>
</Test>
</Root-Element>
</part>
</Receive1_Read_InputVariable>
Thanks,
Nilesh Jha
I am not able to validate the XML using the below XSD,
<myTest>
<standardHeader xmlns="http://tow.gow.ho.com/2009/08/StandardHeader/">
<data>
<LEVELDATA>D2D</LEVELDATA>
</data>
</standardHeader>
</myTest>
XSD Data
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="myTest">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element name="standardHeader" minOccurs="0">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element name="data" minOccurs="0">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element name="LEVELDATA" minOccurs="0" type="xsd:normalizedString"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
I am getting the below error while validating this XSD with XML,
cvc-complex-type.2.4.a: Invalid content was found starting with element 'standardHeader'. One of '{standardHeader}' is expected.
How can I provide this standardHeader tag:
targetNamespace="http://tow.gow.ho.com/2009/08/StandardHeader/"
The problem is the wrong 'namespace' in the XML... (line 2)
When you remove it (or correct it) - it's correct.
Online-Validator
https://www.freeformatter.com/xml-validator-xsd.html
Sample XML-Generator (from XSD)
http://xsd2xml.com/
Namespace-Doc
https://www.w3schools.com/XML/xml_namespaces.asp
One possible solution for this problem is splitting the XSD into two files:
One for the first absent namespace (a.xsd) and one for the second namespace (b.xsd) which is declared by targetNamespace=... in b.xsd while a.xsd does not need that declaration. The second file with its own namespace is imported with the <xsd:import namespace="..." instruction. This namespace has also to be included in a namespace declaration of the xsd:schema element (here xmlns:std).
So a.xsd is:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema elementFormDefault="qualified"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:std="http://tow.gow.ho.com/2009/08/StandardHeader">
<xsd:import namespace="http://tow.gow.ho.com/2009/08/StandardHeader"
schemaLocation="b.xsd" />
<xsd:element name="myTest">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element ref="std:standardHeader" minOccurs="0">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
And b.xsd is:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema elementFormDefault="qualified"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://tow.gow.ho.com/2009/08/StandardHeader">
<xsd:element name="standardHeader">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element name="data" minOccurs="0">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element name="LEVELDATA" minOccurs="0" type="xsd:normalizedString"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
These two XSDs do validate your XML file with its namespace as it is.
This answer was inspired by this webpage: "Multi-Schema Project:
Zero, One, or Many Namespaces?". It does not copy the solutions 1-to-1, but is rather inspired by that webpage.
I have to process big requests in a Java 8 web service (JAX-WS RI). A request contains a "header" and many "records" like this (not that 2nd, 3rd, 4th, 5th student records are invalid according to the schema):
<helloStudentsServiceRequest>
<workshop>
<name>wsname</name>
<tutor>tutorname</tutor>
</workshop>
<studentList>
<!--1 or more repetitions: -->
<student>
<Name>st1</Name>
<Birth>1999-11-11</Birth>
</student>
<student>
<Name>st2</Name>
</student>
<student>
<Name>st2</Name>
<Birth>199O-11-11</Birth>
</student>
<student>
<Name>st3</Name>
<Birth>stoneage</Birth>
</student>
<student>
<Birth>stoneage</Birth>
</student>
<student>
<Name>st6</Name>
<Birth>2001-11-12</Birth>
</student>
</studentList>
</helloStudentsServiceRequest>
I use a schema (XSD) for describing my interface. For example:
<xsd:complexType name="HelloStudentsServiceRequestType">
<xsd:sequence>
<xsd:element name="workshop" type="WorkshopType" />
<xsd:element name="studentList">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="student" type="StudentType" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="WorkshopType">
<xsd:sequence>
<xsd:element name="name" type="xsd:string" />
<xsd:element name="tutor" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="StudentType">
</xsd:annotation>
<xsd:sequence>
<xsd:element name="Name" type="xsd:string" />
<xsd:element name="Birth" type="xsd:date" />
</xsd:sequence>
</xsd:complexType>
I'd like to use this schema for validating the request.
However I am not allowed to reject a request if a few "record" in it is not valid according to the schema. In that case I have to process the valid records and return some meaningful information (preferably the SAX error) regarding the invalid ones.
I'd like to keep the request's schema free from the technical details neccessary to fullfill this "lazy validation". For example I don't want to use a "big string" to hold the "record" and then validate that string against the schema. That would break the interface and would be difficult to communicate to the clients. So this is no-go for me:
...
<xsd:element name="studentList">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="student" type="xsd:string" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
...
Do you know an elegant way to solve this in JAX-WS RI (JAXB2) ?
It's possible to customize JAXB bindings to map part of the XML to DOM. For details:
https://jaxb.java.net/guide/Avoid_strong_databinding.html#Mapping_to_DOM
So I mapped "WorkshopType" and "StudentType" to DOM. Now it's possible to validate those DOMs individually and reject or partially process the incoming message. It's also possible to catch the SAX exception if a DOM validating is not successful and signal that back to the client.
working example zipped
I used this binding customization:
<jxb:bindings version="1.0"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<jxb:bindings
schemaLocation="WorkshopType.xsd"
node="//xsd:complexType[#name='WorkshopType']">
<jxb:dom />
</jxb:bindings>
<jxb:bindings
schemaLocation="StudentType.xsd"
node="//xsd:complexType[#name='StudentType']">
<jxb:dom />
</jxb:bindings>
And these are the schemas:
For the request:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" xmlns="helloStudentsNS"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
targetNamespace="helloStudentsNS">
<xsd:include schemaLocation="StudentType.xsd" />
<xsd:include schemaLocation="WorkshopType.xsd" />
<xsd:element name="helloStudentsServiceRequest" type="HelloStudentsServiceRequestType" />
<xsd:element name="helloStudentsServiceResponse" type="HelloStudentsServiceResponseType" />
<xsd:complexType name="HelloStudentsServiceRequestType">
<xsd:sequence>
<xsd:element name="workshop" type="WorkshopType" />
<xsd:element name="studentList">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="student" type="StudentType" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="HelloStudentsServiceResponseType">
<xsd:sequence>
<xsd:element name="GreetingHeader" type="xsd:string" />
<xsd:element name="StudentGreeting" type="xsd:string" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
For the workshop and student types:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
xmlns="helloStudentsNS"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="2.0"
targetNamespace="helloStudentsNS">
<xsd:element name="workshop" type="WorkshopType"/>
<xsd:complexType name="WorkshopType">
<!-- <xsd:annotation><xsd:appinfo><jaxb:dom/></xsd:appinfo></xsd:annotation> -->
<xsd:sequence>
<xsd:element name="name" type="xsd:string" />
<xsd:element name="tutor" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
xmlns="helloStudentsNS"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="2.0" targetNamespace="helloStudentsNS">
<!--
-->
<xsd:element name="student" type="StudentType"/>
<xsd:complexType name="StudentType">
<!-- <xsd:annotation><xsd:appinfo><jaxb:dom/></xsd:appinfo></xsd:annotation> -->
<xsd:sequence>
<xsd:element name="Name" type="xsd:string" />
<xsd:element name="Birth" type="xsd:date" />
</xsd:sequence>
</xsd:complexType>
And this is the java code:
public HelloStudentsServiceResponseType greetStudents(HelloStudentsServiceRequestType req) {
WorkshopType ws;
// unmarshall workshop data
Element element = req.getWorkshop(); // workshop is retrieved as DOM
try {
Unmarshaller u = jc.createUnmarshaller(); // jaxb ri unmarshaller not thread safe: https://jaxb.java.net/guide/Performance_and_thread_safety.html
u.setSchema(workshopSchema); // enable validation by workshopType.xsd
ws = u.unmarshal(element, WorkshopType.class).getValue(); // unmarshal
} catch (JAXBException e) {
// this is fatal
throw new RuntimeException("fatal: invalid workshop data: ", e);
}
// unmarshall students
List<String> studentGreetings = new ArrayList<>();
for(Element studentElement : req.getStudentList().getStudent()) { // retrieve students as DOMs
try {
StudentType st;
Unmarshaller u = jc.createUnmarshaller(); // jaxb ri unmarshaller not thread safe: https://jaxb.java.net/guide/Performance_and_thread_safety.html
u.setSchema(studentSchema); // enable validation by studentType.xsd
st = u.unmarshal(studentElement, StudentType.class).getValue();
studentGreetings.add("Dear " + st.getName() + ", " + st.getBirth() + ", welcome in the workshop!");
} catch (JAXBException e) {
Throwable cause = e.getLinkedException();
if(cause != null) {
studentGreetings.add("Dear student, your data is invalid: " + cause.getMessage());
}
else {
studentGreetings.add("Dear student, there's an unknown problem with your data");
}
}
}
// construct response
HelloStudentsServiceResponseType response = new HelloStudentsServiceResponseType();
response.setGreetingHeader("I'd like to greet everybody in the " + ws.getName() + " workshop. " +
"Your tutor is " + ws.getTutor());
response.getStudentGreeting().addAll(studentGreetings);
return response;
}
I can't validate xml document against xsd schema.
And I couldn't figure out what is wrong there.
Here is xml file:
<?xml version="1.0" encoding="UTF-8"?>
<staff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="employee.xsd">
<employee>
<name>Carl Cracker</name>
<salary>75000</salary>
<hiredate year="1987" month="12" day="15" />
</employee>
<employee>
<name>Harry Hacker</name>
<salary>50000</salary>
<hiredate year="1989" month="10" day="1" />
</employee>
<employee>
<name>Tony Tester</name>
<salary>40000</salary>
<hiredate year="1990" month="3" day="15" />
</employee>
</staff>
And xsd file:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="staff">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="employee" maxOccurs="unbounded" minOccurs="0">
<xsd:complexType>
<xsd:sequence>
<xsd:element type="xsd:string" name="name"/>
<xsd:element type="xsd:int" name="salary"/>
<xsd:element name="hiredate">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute type="xsd:short" name="year" use="optional"/>
<xsd:attribute type="xsd:byte" name="month" use="optional"/>
<xsd:attribute type="xsd:byte" name="day" use="optional"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
And output is next:
cvc-elt.1: Cannot find the declaration of element 'staff'.
Exception in thread "main" java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.DeferredTextImpl cannot be cast to org.w3c.dom.Element
at com.lab.edu.DOMTreeParser.parseStaff(DOMTreeParser.java:77)
at com.lab.edu.DOMTreeParser.<init>(DOMTreeParser.java:42)
at com.lab.edu.Application.main(Application.java:7)
Here is snippet of code:
public DOMTreeParser(String filename) {
employeeList = new ArrayList<>();
boolean result = validate(filename);
System.out.println("it is validate result: " + result);
if (result == false) {
System.out.println("XML isn't valid");
System.exit(0);
}
// if all are correct - parse xml
parseStaff(document.getDocumentElement());
}
private boolean validate(String filename) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
factory.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
factory.setIgnoringElementContentWhitespace(true);
builder = factory.newDocumentBuilder();
builder.setErrorHandler(new SimpleErrorHandler());
document = builder.parse(new File(filename));
return true;
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
return false;
}
}
I tried to validate xml accord xsd at validator - all was valid.
What is cause of this cvs.. message?
Any suggestions?
The outermost element of your instance document must match a global element declaration in the schema. You only have one global element declaration, for the "staff" element, which is not present in your instance. If you want the "employee" element to validate, you will have to promote it from a local element declaration to a global one, which means rewriting the schema as:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="staff">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="employee" maxOccurs="unbounded" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="employee">
<xsd:complexType>
<xsd:sequence>
<xsd:element type="xsd:string" name="name"/>
<xsd:element type="xsd:int" name="salary"/>
<xsd:element name="hiredate">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute type="xsd:short" name="year" use="optional"/>
<xsd:attribute type="xsd:byte" name="month" use="optional"/>
<xsd:attribute type="xsd:byte" name="day" use="optional"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
I am expecting a XML generated by JAXB which has the following pattern:
<payload>
<parameters>
<paramName>clientAssocIds</paramName>
<paramVal>0207</paramVal>
<paramName>quoteType</paramName>
<paramVal>NTB</paramVal>
<paramName>quoteDateLimitDays</paramName>
<paramVal>365</paramVal>
<paramName>externalIndicator</paramName>
<paramVal>1</paramVal>
</parameters>
</payload>
The <paramName> and <paramVal> are name and value pairs, which means <paramVal> has to follow <paramName>.
I wrote a XML Schema and use JAXB to generate the java class based on this schema, then I set all the values and marshalled the class, it didn't generate the xml pattern I expected above.
Here is my schema:
<xsd:complexType name="sgrpCommonMessage">
<xsd:sequence>
<xsd:element name="payload" type="payload" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="payload">
<xsd:sequence>
<xsd:choice minOccurs="0" maxOccurs="1">
<xsd:element name="parameters" type="parameter" />
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="parameter">
<xsd:sequence>
<xsd:element minOccurs="0" name="paramName" type="xsd:string" />
<xsd:element minOccurs="0" name="paramVal" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
And the generated xml has a few <parameters>, which is not what I expect. I want to wrap all the <paramName> and <paramVal> pairs in one <parameters>:
<payload>
<parameters>
<paramName>quoteDateLimitDays</paramName>
<paramVal>NTB</paramVal>
</parameters>
<parameters>
<paramName>clientAssocIds</paramName>
<paramVal>0207</paramVal>
</parameters>
<parameters>
<paramName>quoteType</paramName>
<paramVal>NTB</paramVal>
</parameters>
<parameters>
<paramName>externalIndicator</paramName>
<paramVal>NTB</paramVal>
</parameters>
</payload>
I am wondering if JAXB is capable of realizing such XML structure, if not, what API should I use, if yes, how?
You could have an XML schema like the following:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="parameters" type="parameters" />
<xsd:complexType name="parameters">
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element name="paramName" type="xsd:string" />
<xsd:element name="paramValue" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
Then with the generated model you could do:
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance("forum14571803");
ObjectFactory objectFactory = new ObjectFactory();
Parameters parameters = objectFactory.createParameters();
parameters.getParamNameAndParamValue().add(objectFactory.createParametersParamName("A"));
parameters.getParamNameAndParamValue().add(objectFactory.createParametersParamValue("a"));
parameters.getParamNameAndParamValue().add(objectFactory.createParametersParamName("B"));
parameters.getParamNameAndParamValue().add(objectFactory.createParametersParamValue("b"));
JAXBElement<Parameters> root = objectFactory.createParameters(parameters);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
Which would give you the following output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<parameters>
<paramName>A</paramName>
<paramValue>a</paramValue>
<paramName>B</paramName>
<paramValue>b</paramValue>
</parameters>