How to add Prefix for the attribute while marshling - java

I like to add prefix for attribute while marshaling using castors.
I would like to get result as like below
<ThesaurusConcept dc:identifier="C268">
<ScopeNote xml:lang="en">
<LexicalValue>index heading is Atomic absorption spectroscopy</LexicalValue>
</ScopeNote>
</ThesaurusConcept>
but I am getting
<ThesaurusConcept identifier="C621">
<ScopeNote lang="en">
<LexicalValue>index heading is Atomic absorption spectroscopy</LexicalValue>
</ScopeNote>
</ThesaurusConcept>

I got an answer for my question
we need to add the following in mapping.xml file
<mapping xmlns:dc="http://purl.org/dc/elements/1.1/">
<bind-xml name="dc:identifier" node="attribute" ></bind-xml>
and also we need to set namespace by using following code.
Marshaller casreactmp = new Marshaller(handler);
casreactmp.setNamespaceMapping("dc", "http://purl.org/dc/elements/1.1/");

Related

Mapping XML with JAXB, when the fields are generic, and the actual field names are mapped elsewhere?

In my java(/spring/hibernate) web app, I am contending with XML like this (I've simplified it down a lot for example purposes - I cannot modify the XML as I'm receiving it from a third party - I only control the client code, and client domain objects - there is no XSD or WSDL to represent this XML either):
<?xml version="1.0" encoding="utf-16"?>
<Records count="22321">
<Metadata>
<FieldDefinitions>
<FieldDefinition id="4444" name="name" />
<FieldDefinition id="5555" name="hair_color" />
<FieldDefinition id="6666" name="shoe_size" />
<FieldDefinition id="7777" name="last_comment"/>
<!-- around 100 more of these -->
</FieldDefinitions>
</Metadata>
<!-- Several complex object we don't care about here -->
<Record contentId="88484848475" >
<Field id="4444" type="9">
<Reference id="56765">Joe Bloggs</Reference>
</Field>
<Field id="5555" type="4">
<ListValues>
<ListValue id="290711" displayName="Red">Red</ListValue>
</ListValues>
</Field>
<Field id="6666" type="4">
<ListValues>
<ListValue id="24325" displayName="10">10</ListValue>
</ListValues>
</Field>
<Field id="7777" type="1">
<P>long form text here with escaped XML here too
don't need to process or derefernce the xml here,
just need to get it as string in my pojo<P>
</Field>
</Record>
<Record><!-- another record obj here with same fields --> </Record>
<Record><!-- another record obj here with same fields--> </Record>
<!-- thousands more records in the sameish format -->
</Records>
The XML contains a 'records' element, which contains some metadata, then lots of 'record' elements. Each record element contains lots of 'field' entries.
My goal would be to use JAXB to unmarshall this XML into a large collection of 'record' objects. So I could do something like this:
List<Record> unmarhsalledRecords = this.getRecordsFromXML(stringOfXmlShownAbove)
where each record would look like this:
public class Record {
private String name;
private String hairColor;
private String shoeSize;
private String lastComment;
//lots more fields
//getters and setters for these fields
}
However, I've never needed to dereference field names in jaxb - is that even possible with jaxb - or do I need to write some messy/hard to maintain code with a stax parser?
None of the examples I can find online touch on anything like this - any help would be greatly appreciated.
Thank you!
I don't think jaxb supports complex mapping logic like. A couple of options that I can think of.
Transform the xml using freemarker or xslt (I hate xslt) to an xml format that matches your desired model before parsing with jaxb
Eg
<Records>
<Record>
<Name>Joe Bloggs</Name>
<HairColour>Red</HairColour>
...
</Record>
</Records>
Parse the xml as is and write an adapter wrapper in the java layer which adapts from the inbound jaxb objects to your more "user friendly" model. The adapter layer could call into the jaxb objects under the hood so you could later serialize back to xml after changes

How get attribute content by another attribute value with XPath?

I have XML like:
<?xml version='1.0' encoding='UTF-8'?>
<ClinicalDocument xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns='urn:hl7-org:v3'
xmlns:ext='urn:hl7-RU-EHR:v1'
xsi:schemaLocation='urn:hl7-org:v3'>
<author>
<time value='20160809000000+0300'/>
<assignedAuthor>
<id root='1.2.643.5.1.13.3.25.1.1.100.1.1.70' extension='1'/>
<id root='1.2.643.100.3' extension='03480134121'/>
<id nullFlavor='NI'/>
</assignedAuthor>
</author>
</ClinicalDocument>
I have to get extension in id with root's value = 1.2.643.100.3.
I must use XPath 2.0.
I have tried:
*[name()='ClinicalDocument']/*[name()='author']/*[name()='assignedAuthor']/*[name()='id' and #id='1.2.643.100.3']/#extension. Not working
/*[name()='ClinicalDocument']/*[name()='author']/*[name()='assignedAuthor']/*[name()='id'][2]/#extension, but order of ids can
mixed. So that, I should retrieve by id's value
It's needed to me for retrieving value by Java's XPathExpression
First, bind namespace prefix, u: to urn:hl7-org:v3.
Then, this XPath,
//u:id[#root='1.2.643.100.3']/#extension
will return 03480134121, as requested.
If you are unable to bind a namespace prefix, you can instead use this XPath,
//*[local-name() ='id' and #root='1.2.643.100.3']/#extension
which will also return 03480134121, as requested.
Correct XPath: /*[name()='ClinicalDocument']/*[name()='author']/*[name()='assignedAuthor']/*[local-name()='id' and #root='1.2.643.100.3']/#extension

How to use xpath in camel when the outermost element has an xmlns attribute?

I am having some trouble using xpath to extract the "Payload" values below using apache-camel. I use the below xpath in my route for both of the example xml, the first example xml returns SomeElement and SomeOtherElement as expected, but the second xml seems unable to parse the xml at all.
xpath("//Payload/*")
This example xml parses just fine.
<Message>
<Payload>
<SomeElement />
<SomeOtherElement />
</Payload>
</Message>
This example xml does not parse.
<Message xmlns="http://www.fake.com/Message/1">
<Payload>
<SomeElement />
<SomeOtherElement />
</Payload>
</Message>
I found a similar question about xml and xpath, but it deals with C# and is not a camel solution.
Any idea how to solve this using apache-camel?
Your 2nd example xml, specifies a default namespace: xmlns="http://www.fake.com/Message/1" and so your xpath expression will not match, as it specifies no namespace.
See http://camel.apache.org/xpath.html#XPath-Namespaces on how to specify a namespace.
You would need something like
Namespaces ns = new Namespaces("fk", "http://www.fake.com/Message/1");
xpath("//fk:Payload/*", ns)
I'm not familiar with Apache-Camel, this was just a result of some quick googling.
An alternative maybe to just change your xPath to something like
xpath("//*[local-name()='Payload']/*)
Good luck.

Jdom2 Sharepoint XML Fields

Having some trouble returning certain fields from a SharePoint List SOAP request.
Here is the XML:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:soap1="http://schemas.microsoft.com/sharepoint/soap/">
<soap:Header/>
<soap:Body>
<soap1:UpdateListItems>
<soap1:listName>69A3FFFA-782B-45D5-B776-2BE6D5645745</soap1:listName>
<soap1:updates>
<Batch OnError="Continue">
<Method ID="1" Cmd="New">
<Field Name="Title">New Item</Field>
</Method>
</Batch>
</soap1:updates>
</soap1:UpdateListItems>
</soap:Body>
</soap:Envelope>
I am able to use the following Jdom2 code to grab certain values like this:
// set your name spaces.
Namespace soap = Namespace.getNamespace("soap","http://www.w3.org/2003/05/soap-envelope");
Namespace soap1 = Namespace.getNamespace("soap1","http://schemas.microsoft.com/sharepoint/soap/");
// drill down into elements
Element rootNode = doc.getRootElement();
// Get Body node
Element body = rootNode.getChild("Body",soap);
// Get UpdateListItem Element
Element UpdateListItems = body.getChild("UpdateListItems",soap1);
// Get updates node
Element updates = UpdateListItems.getChild("updates",soap1);
// Set list name as String variable
String listNameString = UpdateListItems.getChild("listName",soap1).getText();
// Print list text value ** THIS WORKS**
System.out.println(listNameString);
However, I can't seem to figure out how to select the Field elements.
For example: How would I select the "Title" Field?
<Field Name="Title">New Item</Field>
UPDATE:
I also able to get the attribute "Name" from the "Field" element, but can only return or set the name of value of the attribute. I need to be able to access the test within the "Field" Element.
I can get the value of the attribute like this:
System.out.println(field.getAttribute("Name").getValue()); // Prints Title
And I can get the name like this:
System.out.println(field.getAttribute("Name").getName()); // Prints Name
But, I need to be able to return the text value of the element.
UPDATE 2:
I didn't mention. The XML really looks like this:
` <?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:soap1="http://schemas.microsoft.com/sharepoint/soap/">
<soap:Header/>
<soap:Body>
<soap1:UpdateListItems>
<soap1:listName>69A3FFFA-782B-45D5-B776-2BE6D5645745</soap1:listName>
<soap1:updates>
<Batch OnError="Continue">
<Method ID="1" Cmd="New">
<Field Name="Title">New Item</Field>
<Field Name="Classification" Type="Choice">Funny</Field>
<Field Name="Title">New Item</Field>
<Field Name="Title" Type="Text">Funny List Item</Field>
</Method>
</Batch>
</soap1:updates>
</soap1:UpdateListItems>
</soap:Body>
</soap:Envelope>`
I can submit this via SoapUI to SharePoint and it works. But if there are multiple "Field" elements, with different attributes, how can I select the correct one via Jdom2?
I can do this:
String title = field.getText(); //returns New Item
But how would I be able to grab the text from other "Field" elements that use the "Name" attribute?
It is all in the namespaces. You have three of them, soap, soap1, and there's also the default namespace, which, in this case, is "". JDOM designates this namespace as Namespace.NO_NAMESPACE.
So, to get the Field Element from the updates Element, you can do:
Element methods = updates.getChild("Method", Namespace.NO_NAMESPACE);
Element field = methods.getChild("Field", Namespace.NO_NAMESPACE);
These can be made simpler, if you want, by using the getChild method that does not have the namespace parameter at all, like:
Element methods = updates.getChild("Method");
Element field = methods.getChild("Field");
The important thing to see here, is that your document has 3 namespaces, and that the Field element (and Method too) are not in the soap, or soap1 namespace.
Thanks for the help rolfl. I figured it out. You can loop through the Child elements to access the different "Field" attributes. I then test for the attribute name to get or set its content. This is the best I could come up with.
for (Element node : method.getChildren("Field")){
if(node.getAttributeValue("Name").equalsIgnoreCase("Title")){
node.setText("String");
}
System.out.println(node.getAttribute("Name").getValue());
}

Xml id attribute to work with Java's getElementById? [duplicate]

This question already has answers here:
Java DOM getElementByID
(2 answers)
Closed 3 years ago.
I have an xml document being parsed in Java as a w3c document.
In my xml, i have many elements of the same name, e.g <item ..... />, each one with unique attribute's value, e.g <item name="a" .... />.
I want in java to do:
doc.getElementById("a")
in order to get that specific item I have there with that name.
How can I tell java to use 'name' as the id?
Or, alternately, How can I fetch that specific item in least complexity?
DOM is not the best API to easily query your document and get back found elements. Learn XPath, which is a more appropriate API, or iterate through the tree of elements by yourself.
getElementById() will only return the element which has the given id attribute (edit: marked as such in the document DTD or schema). It can't find by name attribute.
See Java XML DOM: how are id Attributes special? for details.
You need to write a DTD that defines your attribute as being of type ID.
Well, To make a complete answer, I had to use DTD schemas like everyone stated.
Since my needs are quite simple, I added it in embedded in my xml the following way:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ATTLIST item
name ID #REQUIRED
>
]>
<root> .... </root>
The only important thing left to know is that once you declare the ATTLIST, I have to declare all of the rest of my attributes, therefore, you need to add IMPLIED:
some-attribute CDATA #IMPLIED
It says that some-attribute contains some data (can use also PCDATA for parsed cdata), and is implied, which means, it can be there or it cannot. doesnt matter.
So eventually, it'll look something like:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ATTLIST item
name ID #REQUIRED
some-attribute CDATA #IMPLIED
>
]>
<root> .... </root>
And from Java side, Just use it blindly, e.g getElementById("some-name")
In order to make doc.getElementById("a") work you need to change your XML to <item id="a" name="a" .... />
If you can't change the XML, you could use XPath to retrieve this element.

Categories