I am trying to write unit tests for my WSDL SOAP web service in Java.
Problem occurs, when I try to assert XML equality, of how response from web service should look like and what it actually looks like.
I have no idea why I get the following error:
Expected namespace prefix "pns111", but was "ns3"
So here, pns111 is my defined namespace for web service. Why do I receive ns3 namespace? And why specifically ns3? I have not defined ns3 namespace anywhere, is this namespace somehow special?
Also, I get another error regarding XML equality assertion:
Expected presence of child nodes to be 'true', but was 'false'.
Can you give me any clue of this error as well?
In XML the prefix used for a namespace need not be the same for two XML documents to be considered equal. It helps to think of the namespace prefix as nothing more than an abbreviation for the namespace URI.
These two XML documents are the same from an XML processing standpoint:
<?xml version="1.0" encoding="UTF-8"?>
<foo:root xmlns:foo="http://example.com">
<foo:node>Hi!</foo:node>
</foo:root>
And:
<?xml version="1.0" encoding="UTF-8"?>
<bar:root xmlns:bar="http://example.com">
<bar:node>Hi!</bar:node>
</bar:root>
In the first example foo means “the http://example.com namespace”. In the second one bar too points to the same namespace.
So in your test you should be verifying that the namespace URI matches the expected one. Which prefix is used is not relevant, as long as it is consistent within the XML document.
It depends on the library generating your XML if it will use the prefix you specified or pick one itself.
Related
I have the situation there is an web service implemented in old Visual Studio 2008, which accepts the SOAP requests with content having namespaces only in this form:
<Root xmlns="http://A">
<A>
<A1 />
</A>
<B xmlns="http://B">
<B1 />
</B>
</Root>
All other forms of the XML (unqualified, or qualified with namespace prefix) are causing problems even if the wsdl and referenced xsd structures are manipulated and modified in various ways and the service is recompiled in Visual Studio 2008, the author of the ASP.NET web service is not able to get any other form of XML working.
Is there any way how to achieve the generation of the classes for our Java client accessing this web service by using the external JAXB binding specification, used during the class generation, so the XML would be from the objects marshalled in the above described form?
Am I right, if I think, this could be achieved by the forcing the JAXB to generate the class(ses in multiple directories)
package-info.java
instead of the default form
#javax.xml.bind.annotation.XmlSchema(
namespace = "http://some/custom/namespace",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package some.custom.namespace;
in the following form?
#javax.xml.bind.annotation.XmlSchema(
namespace = "http://some/custom/namespace",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
xmlns = {#XmlNs(prefix = "", namespaceURI = "http://some/custom/namespace")})
package some.custom.namespace;
and if I am right, is there any way to do it? I am unfamiliar with writing the XJB bindings, so any pointer would be appreciated...
Or maybe, after the generation the source code of this class should be postprocessed by something like ant task, which would modify the initially generated JAXB form into the form I think it was the desired content of the class package-info.java?
Could this be somehow achieved by one universal jxb binding file for all usages without necessity to modify it for every namespace folder creating its own package?
I hope this could really work even with multiple different namespaces without prefixes, because the xmlns definitions are then used in JAXBContextImpl as a set of XmlNs types, so if there is an prefix or not hopefully should not matter... Am I right?
I have generated Java classes from an XSD, and in my XML responses I am getting a ns2: prefix which I do not need.
For example, I am getting this response:
<ns2:location xmlns:ns2="http://www.example.com/">
<ns2:response/>
</ns2:location>
But the response I am expecting is as follows:
<location>
<response/>
</location>
Your example shows not just a namespace prefix (ns2) declaration but also an actual namespace (http://www.example.com/ for the location and response elements) as not being desired.
If you have full control over the XSD, you can remove the
targetNamespace="http://www.example.com/"
attribute from the xs:schema element in the XSD. Elements of XML documents conforming to this XSD will then no longer be in any namespace, and your generated Java classes will reflect this new setting.
However, be aware that deleting (or changing) targetNamespace effectively changes the names of the components defined in the XSD. Think twice about making such a change if the XSD is defined by another party or otherwise already in use by others.
Is it possible to bind xml prefix→namespace mapping to a map using javax.xml.bind.* annotations?
Something like:
class FooPOJO {
...
#Namespacebindingannotation
Map<String,String> prefixToNamespaceMap;
...
}
And in the xml
<foo
xmlns="http://foo.com"
xmlns:bar="http://bar.com"
xmlns:baz="http://baz.com">
...
When unmarshaling the xml, prefixToNamespaceMap will map the 3 prefixes to their appropriate namespaces.
You want to dynamically extract the namespaces URIs and the prefixes from the XML? That's a genuinely bad idea.
XML namespaces are part of the contract between your application code and the XML it processes. They ought to be hard-coded into your application.
The reason is simple. These XMLs look different but are all the same document:
<foo:root xmlns:foo="http://main/ns" xmlns:bar="http://secondary/ns">
<foo:child bar:attr="1234">some data</foo:child>
</foo:root>
or
<bar:root xmlns:bar="http://main/ns" xmlns:foo="http://secondary/ns">
<bar:child foo:attr="1234">some data</bar:child>
</bar:root>
or
<root xmlns="http://main/ns" xmlns:baz="http://secondary/ns">
<child baz:attr="1234">some data</child>
</root>
So if you extract namespaces dynamically from them, your subsequent code will inevitably (and unnecessarily) break.
Use actual namespace URIs in your code and choose prefixes to your liking - prefixes are ephemeral, they don't have to match up with the XML files. XML is strongly typed data, treat it accordingly.
In other words, namespace prefixes are aliases, a convenience facility, they only exist in serialized data. They exist in XML, they don't exist in the DOM. They exist in your application's XPath expressions, they don't exist in the abstract tree the XPath expressions are parsed into. Those are two completely separate domains. If the same prefixes are used in both domains, that's entirely coincidental. Don't build application logic that transfers prefixes from one domain to the other, as this is bound to break.
I am creating amazon feed, the feed xml should be like:
<AmazonEnvelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="amzn-envelope.xsd">
I am using jaxb to generate xml files from java classes, I used NamespacePrefixMapperImpl from jaxb samples to add namespaces to the xml. But currently it generates the root like:
<AmazonEnvelope xmlns:xsi:noNamespaceSchemaLocation="amzn-envelope.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
how I can remove the xmlns from amzn-envelope.xsd??
Here's the mapping I used in NamespacePrefixMapperImpl
if( "http://www.w3.org/2001/XMLSchema-instance".equals(namespaceUri) )
return "xsi";
if("amzn-envelope.xsd".equals(namespaceUri))
return "xsi:noNamespaceSchemaLocation";
I found a property at Marshaller that can add the amzn-envelope.xsd:
marshaller.setProperty("jaxb.noNamespaceSchemaLocation", "amzn-envelope.xsd");
and left the NamespacePrefixMapper to add the "http://www.w3.org/2001/XMLSchema-instance".
Hope this helps others.
If I understand your intent, your document has a default namespace, and you're trying to add the schemalLocation for that namespace.
NamespacePrefixMapper won't let you do this, it's useful only for picking a prefix for a namespace. There are no namespaces in this document, and so no useful way of using NamespacePrefixMapper. It can't be used for adding schemaLocation hints - those are treated specially by JAXB, and you're just confusing it.
Are you sure you need the noNamespaceSchemaLocation="amzn-envelope.xsd" at all? Have you tried sending it to the web service without it?
I am connecting to a webservice which has a service deifnition of the following format
<main>
<header>
<data>xyz</data>
</header>
<test>
<![CDATA[<xml><a></a><b></b></xml>]]>
</test>
</main>
How do I use jaxb to create class file for the cdata strcture
First define your schema using the xml-schema format (XSD), and then run the xjc compiler (xsd java compiler) to generate your classes. Once you classes are generated you can create your web service using the #WebService annotation. I posted somes examples on my blog a few monthes ago see: http://plindenbaum.blogspot.com/2006/12/java-16-mustang-jaxb-and.html and http://plindenbaum.blogspot.com/2008/11/web-service-for-onsolubility.html.
hope it helps
JAXB will not be able to parse anything wrapped in a CDATA declaration: the XML parser will always report the string.
If you want to parse this, you need to do the following:
Run JAXB on the original schema, which will specify the content of "test" as a string or "any" (it has to, otherwise it cannot contain a CDATA declaration!)
Run JAXB on the secondary schema, which defines the content of the "test" element.
At runtime, you need to parse the XML document using JAXB, then navigate to the "test" element and parse that element again using JAXB. There won't be another way.
Hope this helps.