How to convert object to XML document - java

I have imported WSDL files and I'm trying to create a web service client.
In this case I could able to send soap request (XML) and also can get the result as a object(Using sout),
com.ech.cdem.client.AppointmentUpdateResponseAppointmentUpdateResult#45d6cba4
I could understand com.ech.cdem.client.AppointmentUpdateResponseAppointmentUpdateResult is a package.class name.
So result should be #45d6cba4 as a object.
when I debug this object(whole result) and evaluate the result.then I could able to get expected result XML response.
<data-set xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns=""><record><STATUS>Success</STATUS><MESSAGE>Appointment Number : 000262</MESSAGE></record></data-set>
how to print like that object as a xml document or something like...
further,
AppointmentUpdateResponseAppointmentUpdateResult result = service.appointmentUpdate(xmlInput);
System.out.println(result);
xmlInput is a String(request XML document) and AppointmentUpdateResponseAppointmentUpdateResult is a class.

In my IDE (Intellij IDEA), I have an option called "Evaluate Expression". What it does is when debug some value (eg: "result" object), by changing that expression(debug value) we can evaluate (get) the result without running the program.
That's how I got my result.
In my case XML file came as an array.
Since how I got my output,
result.get_any()[0].getElementsByTagName("record").item(0).getChildNodes().item(0).getChildNodes().item(0).toString()
Without "Evaluate Expression" that kind of expression was imposible. So my advice is use your IDE's "Evaluate Expression" option.

Related

Convert XML to and from Java

I am trying to get the XML response from the rest API. And I am getting JSON response for all customers and XML for single customer from API. PFB the screen print for the case for both cases:
Case 1: When URL= http://localhost:8080/spring-crm-rest/api/customers/ then I am getting JSON response
JSON Response
Case 2: When URL = http://localhost:8080/spring-crm-rest/api/customers/1 then I am getting XML response
XML Response
Please find below the URL for the complete code to replicate the same at your end.
Link for the code: https://drive.google.com/file/d/1fd7DyUsfOvY4fX0nm6j4fzrwxHyg9ZGz/view?usp=sharing
Ok I think the reason why that happens is the following:
the path /spring-crm-rest/api/customers/ has return type List<Customer> -> default java List as top level -> json result
while /spring-crm-rest/api/customers/1 has return type Customer as top level which has the javax.xml.bind annotations -> xml result
Changing this may be a bit tricky but these are some possible things you can try:
specifically set the content type of the endpoint like this: #GetMapping(produces = {"application/json"})
removing the #Xml.* annotations -> spring will can serialize the class without any annotations but without them you have less of a control over the resulting json (e.g. renaming fields, etc). Depending on your usecase it might not be needed though

Generating Java code from transformation JSON to a XML

I wonder do you now any program that can generate for me a Java code from transformation JSON to a XML? In Altova MapForce there is such a possibility, but unfortunately when I want use it, it returns me an Error:
Altova_Hierarchical_JSON.mfd: Mapping validation failed - 1 error(s), 0 warning(s)
Altova_Hierarchical: JSON components are not supported for Java.
The output component Altova_Hierarchical has no output file name set. A default file name will be used.
The second thing, that is important for me, is capabilities to create graphic mapping between JSON and XML like example below shows:
Thanks for the reply.
There is underscore-java library with static method U.xmlToJson(xml). I am the maintainer of the project.
<anyxml>data</anyxml>
Output:
{
"anyxml": "data",
"#omit-xml-declaration": "yes"
}

Retrieve value of attribute using XPath

I am trying to retrieve the value of an attribute from an xmel file using XPath and I am not sure where I am going wrong..
This is the XML File
<soapenv:Envelope>
<soapenv:Header>
<common:TestInfo testID="PI1" />
</soapenv:Header>
</soapenv:Envelope>
And this is the code I am using to get the value. Both of these return nothing..
XPathBuilder getTestID = new XPathBuilder("local-name(/*[local-name(.)='Envelope']/*[local-name(.)='Header']/*[local-name(.)='TestInfo'])");
XPathBuilder getTestID2 = new XPathBuilder("Envelope/Header/TestInfo/#testID");
Object doc2 = getTestID.evaluate(context, sourceXML);
Object doc3 = getTestID2.evaluate(context, sourceXML);
How can I retrieve the value of testID?
However you're iterating within the java, your context node is probably not what you think, so remove the "." specifier in your local-name(.) like so:
/*[local-name()='Header']/*[local-name()='TestInfo']/#testID worked fine for me with your XML, although as akaIDIOT says, there isn't an <Envelope> tag to be seen.
The XML file you provided does not contain an <Envelope> element, so an expression that requires it will never match.
Post-edit edit
As can be seen from your XML snippet, the document uses a specific namespace for the elements you're trying to match. An XPath engine is namespace-aware, meaning you'll have to ask it exactly what you need. And, keep in mind that a namespace is defined by its uri, not by its abbreviation (so, /namespace:element doesn't do much unless you let the XPath engine know what the namespace namespace refers to).
Your first XPath has an extra local-name() wrapped around the whole thing:
local-name(/*[local-name(.)='Envelope']/*[local-name(.)='Header']
/*[local-name(.)='TestInfo'])
The result of this XPath will either be the string value "TestInfo" if the TestInfo node is found, or a blank string if it is not.
If your XML is structured like you say it is, then this should work:
/*[local-name()='Envelope']/*[local-name()='Header']/*[local-name()='TestInfo']/#testID
But preferably, you should be working with namespaces properly instead of (ab)using local-name(). I have a post here that shows how to do this in Java.
If you don't care for the namespaces and use an XPath 2.0 compatible engine, use * for it.
//*:Header/*:TestInfo/#testID
will return the desired input.
It will probably be more elegant to register the needed namespaces (not covered here, depends on your XPath engine) and query using these:
//soapenv:Header/common:TestInfo/#testID

Xpath transformation not working in java

This is my xml document. I want to sign only the userID part using xml signature. I am using xpath transformation to select that particular element.
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
Version="2.0" IssueInstant="2012-05-22T13:40:52:390" ProtocolBinding="urn:oasis:na
mes:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="localhos
t:8080/consumer.jsp">
<UserID>
xyz
</UserID>
<testing>
text
</testing>
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
http://localhost:8080/saml/SProvider.jsp
</saml:Issuer>
</samlp:AuthnRequest>
I am using the following code to add the transformations :
transformList.add(exc14nTransform);
transformList.add(fac.newTransform(Transform.XPATH, new XPathFilterParameterSpec("samlp:AuthnRequest/UserID xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"")));
But I get the following :
Original Exception was javax.xml.transform.TransformerException: Extra illegal t
okens: 'xmlns', ':', 'samlp', '=', '"urn:oasis:names:tc:SAML:2.0:protocol"'
So, I tried removing the xmlns part.
transformList.add(fac.newTransform(Transform.XPATH, new XPathFilterParameterSpec("samlp:AuthnRequest/UserID")));
But it signs the whole document and gives the following message :
com.sun.org.apache.xml.internal.security.utils.CachedXPa
thFuncHereAPI fixupFunctionTable
INFO: Registering Here function
What is the problem?
EDIT
As #Jörn Horstmann said the message is just a log or something like that. Now the problem is that even after giving the xpath query the whole document is signed instead of just the UserID. I confirmed this by changing the value of <testing>element after signing the document. The result is that the document does not get validated(If it signed only the UserID part, then any changes made to <testing> should result in a valid signature .)
This is not a valid xpath expression, there is no way to declare namespace prefixe inside the expression.
samlp:AuthnRequest/UserID xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
XPathFilterParameterSpec does have another constructor that allows to specify a mapping of namespace prefixes, you could try the following expression:
new XPathFilterParameterSpec("samlp:AuthnRequest/UserID",
Collections.singletonMap("samlp", "urn:oasis:names:tc:SAML:2.0:protocol"))
Edit:
The message does not seem to be an error, see line 426 here, its log level should probably be lower than INFO though.
I also had a look at the description of xpath filtering:
The XPath expression appearing in the XPath parameter is evaluated once for each node in the input node-set. The result is converted to a boolean. If the boolean is true, then the node is included in the output node-set. If the boolean is false, then the node is omitted from the output node-set.
So the correct xpath expression to only include the UserID in the signature would be self::UserID. But don't ask me if this actually makes sense for a xml signature. The example in the specification seems to use a xpath expression to include everything except the signature element itself:
not(ancestor-or-self::dsig:Signature)
Edit 2:
The correct expression is actually ancestor-or-self::UserID since the filter also has to include the text child nodes of the UserID node.

Saxon 8 (Java version) problem

I'll point out now, that I'm new to using saxon, and I've tried following the docs and examples in the package, but I'm just not having luck with this problem.
Basically, I'm trying to do some xml processing in java using saxon v8. In order to get something working, I took one of the sample files included in the package and modified to my needs. It works so long as I'm not using namespaces, and that is my question. How can I get around the namespace problem? I don't really care to use it, but it exists in my xml, so I either have to use it or ignore it. Either solution is fine.
Anyway, here is my starter code. It doesn't do anything but take an xpath query try to use it against the hard coded xml doc.
public static void main(String[] args) {
String query = args[0];
File XMLStream=null;
String xmlFileName="doc.xml";
OutputStream destStream=System.out;
XQueryExpression exp=null;
Configuration C=new Configuration();
C.setSchemaValidation(false);
C.setValidation(false);
StaticQueryContext SQC=new StaticQueryContext(C);
DynamicQueryContext DQC=new DynamicQueryContext(C);
QueryProcessor processor = new QueryProcessor(SQC);
Properties props=new Properties();
try{
exp=processor.compileQuery(query);
XMLStream=new File(xmlFileName);
InputSource XMLSource=new InputSource(XMLStream.toURI().toString());
SAXSource SAXs=new SAXSource(XMLSource);
DocumentInfo DI=SQC.buildDocument(SAXs);
DQC.setContextNode(DI);
SequenceIterator iter = exp.iterator(DQC);
while(true){
Item i = iter.next();
if(i != null){
System.out.println(i.getStringValue());
}
else break;
}
}
catch (Exception e){
System.err.println(e.getMessage());
}
}
An example XML file is here...
<?xml version="1.0"?>
<ns1:animal xmlns:ns1="http://my.catservice.org/">
<cat>
<catId>8889</catId>
<fedStatus>true</fedStatus>
</cat>
</ns1:animal>
If I run this with a query including the namespace, I get an error. For example:
/ns1:animal/cat/ gives the error: "Prefix ns1 has not been declared".
If I remove the ns1: from the query, it gives me nothing. If I doctor the xml to remove the "ns1:" prepended to "animal" I can run the query /animal/cat/ with success.
Any help would be greatly appreciated. Thanks.
Error message correctly points out that your xpath expression does not indicate what namespace prefix "ns1" means (binds to). Just because document to operate on happens to use binding for "ns1" does not mean it is what should be used: this because in XML, it's the namespace URI that matters, and prefixes are just convenient shortcuts to the real thing.
So: how do you define the binding? There are 2 generic ways; either provide a context that can resolve the prefix, or embed actual URI within XPath expression.
Regarding the first approach, this email from Saxon author mentions JAXP method XPath.setNamespaceContext(), similarly, Jaxen XPath processor FAQ has some sample code that could help
That's not very convenient, as you have to implement NamespaceContext, but once you have an implementation you'll be set.
So the notation approach... let's see: Top Ten Tips to Using XPath and XPointer shows this example:
to match element declared with namespace like:
xmlns:book="http://my.example.org/namespaces/book"
you use XPath name like:
{http://my.example.org/namespaces/book}section
which hopefully is understood by Saxon (or Jaxen).
Finally, I would recommend upgrading to Saxon9 if possible, if you have any trouble using one of above solutions.
If you want to have something working out of the box, you can check out embedding-xquery-in-java. There's github project, which uses Saxon to evaluate some sample XQuery expressions.
Regards

Categories

Resources