Validate XML against 2 XSD - validation

I'm trying to parse and validate a SOAP request with SAX. Two XSD are necessary, one for SOAP envelope (http://schemas.xmlsoap.org/soap/envelope/) and the one I defined. I cannot find a way to properly validate the request against these two XSD.
Here's the code I use to parse the request and validate it against soapenv.xsd. It works fine. If I specify my XSD instead, the validation fails with "Cannot find the declaration of element 'soapenv:Envelope'".
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(true);
SAXParser saxParser = factory.newSAXParser();
saxParser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
saxParser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", MyClass.class.getResourceAsStream("/xml/soapenv.xsd"));
InputSource is = new InputSource(MyClass.class.getResourceAsStream("/xml/request.xml"));
XMLReader reader = saxParser.getXMLReader();
reader.setContentHandler(new MyHandler());
reader.setErrorHandler(new MyErrorHandler());
reader.parse(is);
How can I specify a second XSD?
Is there a better way to parse and validate SOAP requests?
EDIT
As proposed, I created thirdpty.xsd that imports my two XSDs.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="thirdparty:general"
xmlns="thirdparty:general"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import schemaLocation="D:\ucfed\ValidateWSDL\src\xml\soapenv.xsd"
namespace="http://schemas.xmlsoap.org/soap/envelope/"/>
<xs:import schemaLocation="D:\ucfed\ValidateWSDL\src\xml\Presence.xsd"
namespace="thirdparty:presence"/>
</xs:schema>
I specify this new XSD for the validation:
saxParser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", MyClass.class.getResourceAsStream("/xml/thidpty.xsd"));
But still, only the SOAP envelope XSD is used for validation. If a modify one element from my other XSD, the validation does not detect it.
Here is the xml I am trying to validate
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="thirdparty:presence">
<soapenv:Header/>
<soapenv:Body>
<urn:getPresenceQuery>
<urn:origAccount uri="test#origin.com"/>
<urn:destAccount uri="test#destination.com"/>
</urn:getPresenceQuery>
</soapenv:Body>
</soapenv:Envelope>
Other ideas ?

Write a driver schema document which imports the other two; validate against the driver.

Related

How to add saml: XML prefix when creating LightSAML IDP response

When generating a response, LightSAML IDP samples show it generates Attributes as mapping rules in the URL format:
<AttributeStatement>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress">
<AttributeValue>email#example.com</AttributeValue>
</Attribute>
</AttributeStatement>
Is there a way to tell LightSAML to generate Attributes as constructs in the generic format, like SimpleSAMLPHP does:
<saml:AttributeStatement>
<saml:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
<saml:AttributeValue xsi:type="xs:string">email#example.com</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
Apologies if I am using the incorrect terminology in my above question. Still learning SAML.

SOAP UI Property transfer from JDBC request into SOAP Request

I have successfully created a JDBC request which is obtaining data from a db in the following XML:
<Results>
<ResultSet fetchSize="64">
<Row rowNumber="1">
<POLICY>9999</POLICY>
<CUSTOMER>00001</CUSTOMER>
</Row>
</ResultSet>
</Results>
I have a SOAP Request and I am trying to pass in both policy and customer values into specific locations on my request. I have set up a Property Transfer step to facilitate this.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://www.xxxxxxxxx.com/services" xmlns:v11="http://www.xxxxxxxxx.com/types" xmlns:v12="http://www.xxxxxxxxx.com/common">
<soapenv:Header/>
<soapenv:Body>
<v1:ReqMessage>
<v11:ServiceHeader>
<v11:CommonHeader>
<v11:ServiceName>Treatment</v11:ServiceName>
<v11:DateTimestamp>2017-02-10T10:51:00.000</v11:DateTimestamp>
</v11:CommonHeader>
<v11:ClientHeader>
<v11:SourceSystem>System</v11:SourceSystem>
</v11:ClientHeader>
<v11:SecurityHeader>
<v11:Username>9A</v11:Username>
</v11:SecurityHeader>
</v11:ServiceHeader>
<v1:ServiceBody>
<v12:TreatmentRequest>
<v12:PolicyNumber></v12:PolicyNumber>
<v12:MemberNumber></v12:MemberNumber>
</v12:GetTreatmentTypesRequest>
</v1:ServiceBody>
</v1:GetProdAndTreatTypesReqMessage>
</soapenv:Body>
</soapenv:Envelope>
I'm struggling to know the Xpath for both source and target to insert into the Property Transfer step.
I am not using SOAP UI Pro.

Xpath not working in camel route

I'm sending soap xml through exchange object.When i try to route the request using xpath in apache camel,i'm not able to execute it properly.Please suggest
My Exchange body xml is
<Envelope><Header>
</Header>
<Body>
<Choice>
<Selector>1</selector>
</Choice>
</Body>
</Envelope>
My Camel Route
from(direct:XX)
.to(when(xpath("body()/Choice/Selector/.",String.class)=='1')
.to("direct:X")
.otherwise()
.to("direct:Y")
your Envelope cannot look like that. it must be something like:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
...
body()/Choice/Selector/. is not an Xpath. there is no such thing like body() in XPath.
Assuming that you have a SOAP Body content in the Exchange.body processed by some JAX-WS endpoint XPath will be
/Choice/Selector or /Choice/Selector/text() if it is an element with mixed content
BTW: if your Envelope is real example you try to test do not forget to fix your XML - you have wrong <Selector>1</selector> Tag names are case sensitive. It must be <Selector>1</Selector>

How to consume XML with more than one possible root element in Spring REST client

In my application I have to consume a service provided by a third party application. The response they provide is always 200 and they change the body based on whether data is available or not or error occurred, as given below
If data is there then
<products>
<product></product>
<product></product>
</products>
If data is empty then
<message> No record found </message>
If some validation failed then
<error>Invalid Id</error>
I am using RestTemplate.exchange to consume the service, my question is if there only single type of root element then we pass the respective class as ParameterizedTypeReference but here how to map the response and unmarshall it.
Use jaxb or jackson to unmarshall the xml.
The right thing to do here is to ask the third party to change their service response to have a root tag. The response object would then look something like this:
<response>
<products>
<product></product>
<product></product>
</products>
<message> No record found </message>
<error>Invalid Id</error>
</response>
With this, you will only need to be concerned about response object and you can check the presence of respective sub-tags.
Other option to make this work for you is to do the exchange by passing String.class as the type reference. Then you would need to do the check in your code to see if the string response returned is products or message or error

Parsing SOAP response using libxml in Ruby

I am trying to parse following SOAP response coming from Savon SOAP api
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns:getConnectionResponse xmlns:ns="http://webservice.jchem.chemaxon">
<ns:return>
<ConnectionHandlerId>connectionHandlerID-283854719</ConnectionHandlerId>
</ns:return>
</ns:getConnectionResponse>
</soapenv:Body>
</soapenv:Envelope>
I am trying to use libxml-ruby without any success. Basically I want to extract anything inside tag and the connectionHandlerID value.
As you are using Savon you can convert the response to a hash. The conversion method response.to_hash does some other useful things for you as well.
You would then be able to get the value you want using code similar to the following
hres = soap_response.to_hash
conn_handler_id = hres[:get_connection_response][:return][:connection_handler_id]
Check out the documentation
I'd recommend nokogiri.
Assuming your XML response is in an object named response.
require 'nokogiri'
doc = Nokogiri::XML::parse response
doc.at_xpath("//ConnectionHandlerId").text

Resources