How to ignore parent tag while unmarshalling to Object - parent

For the below Xml, while unmarshalling to an object, "OperatingHours" tag needs to be ignored, such that only hours tags will be considered for unmarshall.
<Location locale="en-US">
<TelephoneNumber>
<FunctionalTypeDescription>xxx</FunctionalTypeDescription>
<PhoneNumber>00000</PhoneNumber>
</TelephoneNumber>
<OperatingHours>
<Hours>
<ShortName>xxx</ShortName>
<FullName>aaaa</FullName>
</Hours>
<Hours>
<ShortName>yyy</ShortName>
<FullName>bbb</FullName>
</Hours>
</OperatingHours>
I have my Object as follows :
Class AAA {
private List<TelephoneNumber> phnums;
private List<Hours> hours;
}
I don't want to create a separate class called "OperatingHours" for wrapping the hours object. In simple please XML should be as follows.
Any help highly appreciated. Thanks
<Location locale="en-US">
<TelephoneNumber>
<FunctionalTypeDescription>xxx</FunctionalTypeDescription>
<PhoneNumber>00000</PhoneNumber>
</TelephoneNumber>
<Hours>
<ShortName>xxx</ShortName>
<FullName>aaaa</FullName>
</Hours>
<Hours>
<ShortName>yyy</ShortName>
<FullName>bbb</FullName>
</Hours>
</Location>

Related

How to access xml field with lxml?

Python 3.6, Lxml, Windows 10
I am getting crazy. I want to access the item field. But I always get the error:
AttributeError: 'cython_function_or_method' object has no attribute'item'
Everything else (address fields etc...) I can access without problems. How can I access the item fields (sku, amount etc...)?
I've used this code:
import requests
from lxml import objectify
url = "URL_TO_XML_FILE"
xml_content = requests.get(url).text.encode('utf-8')
xml = objectify.fromstring(xml_content)
for sale in xml.response.sales.sale:
for item in sale.items.item:
print(item.sku)
Here is the beginning of the xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<getnewsalesresult xmlns="https://pmcdn.priceminister.com/res/schema/getnewsales">
<request>
<version>2017-08-07</version>
<user>SELLER</user>
</request>
<response>
<lastversion>2017-08-07</lastversion>
<sellerid>95029358</sellerid>
<sales>
<sale>
<purchaseid>297453287592813953</purchaseid>
<purchasedate>15/12/2018-19:10</purchasedate>
<deliveryinformation>
<shippingtype>Normal</shippingtype>
<isfullrsl>N</isfullrsl>
<purchasebuyerlogin><![CDATA[LOGIN]]></purchasebuyerlogin>
<purchasebuyeremail>EMAIL</purchasebuyeremail>
<deliveryaddress>
<civility>Mme</civility>
<lastname><![CDATA[Lastname]]></lastname>
<firstname><![CDATA[Firstname]]></firstname>
<address1><![CDATA[STREET]]></address1>
<address2><![CDATA[]]></address2>
<zipcode>13570</zipcode>
<city><![CDATA[Paris]]></city>
<country><![CDATA[France]]></country>
<countryalpha2>FX</countryalpha2>
<phonenumber1></phonenumber1>
<phonenumber2>PHONENUMBER</phonenumber2>
</deliveryaddress>
</deliveryinformation>
<items>
<item>
<sku><![CDATA[SKU1]]></sku>
<advertid>411812243030</advertid>
<advertpricelisted>
<amount>15.99</amount>
<currency>EUR</currency>
</advertpricelisted>
<itemid>551131040</itemid>
<headline><![CDATA[HEADLINE]]></headline>
<itemstatus><![CDATA[REQUESTED]]></itemstatus>
<ispreorder>N</ispreorder>
<isnego>N</isnego>
<negotiationcomment></negotiationcomment>
<price>
<amount>15.99</amount>
<currency>EUR</currency>
</price>
<isrsl>N</isrsl>
<isbn></isbn>
<ean>4363745894373857474; </ean>
<paymentstatus><![CDATA[INCOMING]]></paymentstatus>
<sellerscore></sellerscore>
</item>
</items>
</sale>
<sale>
The problem is that items is actually a method of ObjectifiedElement, so the expression sale.items actually returns the method, because it has precedence.
To get the 'items' object you want, you have to be more explicit about getting the attribute of sale and not looking for methods of the class first, which is the usual python order. This is what python does behind the scene when you access an attribute, and you can do it too:
sale.__getattr__('items')
This will also work (it's a dictionary-like interface to the attributes of an object):
sale.__dict__['items']
The revised code:
import requests
from lxml import objectify
url = "URL_TO_XML_FILE"
xml_content = requests.get(url).text.encode('utf-8')
xml = objectify.fromstring(xml_content)
for sale in xml.response.sales.sale:
for item in sale.__dict__['items'].item:
print(item.sku)
Another way to deal with this is to avoid using the flaky attribute interface:
for sale in xml['response']['sales']['sale']:
for item in sale['items']['item']:
print(item['sku'])
Using the dict-like indexing interface, you never have to worry about certain attributes names (which includes such common words as items, index, keys, remove, replace, tag, set, text, and values) returning surprising results.

How to get the Structure/Template id by Structure/Template name

I have a requirement that, Need to create JournalArticle with Structure and Template.While creating JournalArticle the method expecting the StructureId and TemplateId but these are generated by Liferay.So by name how can i get Id's of both.
Create and execute a DynamicQuery, like so (just replace Template with Structure to get structures):
DynamicQuery q = DynamicQueryFactoryUtil.forClass(DDMTemplate.class)
.add(PropertyFactoryUtil.forName("name").like("%YOUR NAME%"));
List<DDMTemplate> templates = DDMTemplateLocalServiceUtil.dynamicQuery(q);
You have to use like since the names of the structures/templates are saved like so:
<?xml version='1.0' encoding='UTF-8'?>
<root available-locales="de_DE" default-locale="de_DE">
<Name language-id="de_DE">YOUR NAME</Name>
</root>
There can be different names for different locales.
You can get StructureId (called DDMStructure) with this code
long classNameIdJournalArticle = ClassNameLocalServiceUtil.getClassNameId(JournalArticle.class);
DDMStructure ddmStructure = DDMStructureLocalServiceUtil.getStructure(groupId, classNameIdJournalArticle, "myDDMStructureName");
And TemplateId (called DDMTemplate) with this code
DDMTemplate ddmTemplate = DDMTemplateLocalServiceUtil.getTemplate(groupId, classNameIdDDMStructure, "ddmTemplateName");

JAXB -field based on two sibling XML elements

for example i have this xml:
<xml>
<a>1</a>
<b>2</b>
</xml>
and this class:
#XmlRootElement(name = "xml")
public class xml{
int aPlusb;
....
}
i know how to create an XmlAdapter but i would like it to set the filed aPlusb to be the plus between the value of element a and the value of filed b.
is there a way to do this in JAXB without making an XmlTransient field and calculate it separately?

JAXB marshalling of user extended a Date object always results in empty XML

I have a a class that has many fields, some of which are dates. Specifically, they are MyDate objects, where my MyDate class extends java.util.Date.
When I marshal my top-level class, the date fields show up in the resulting XML, but have no contents. BTW I have verified that the fields in my top-level object are not null, they do reference legitimate MyDate objects. So I get XML that looks like
<TopLevelObject>
<address>1234</address>
<startDate></startDate>
<endDate></endDate>
. . .
</TopLevelObject>
I tried annotating the MyDate class so that I could marshal a single MyDate object, and I get basically the same results:
<MyDate></MyDate>
I have confirmed that the object that I'm marshaling exists and contains a reasonable date.
Is there something about marshaling an object of a derived class that I don't understand?
I've tried turning on Jaxb debugging (by putting -Djaxb.debug=true) on the java command line. That results in some output, but nothing that I find helpful.
EDIT: Before Blaise responded, I tried adding
#XmlSchemaType(name = "date")
just before the declaration of each MyDate attribute in my model class. This seemed to cause the marshaling code to crash partway through creating the XML. The resulting XML just stops in mid-line; there is no indication anywhere of an exception being thrown or a stack trace or anything like that.
Your class MyDate which is an extension of java.util.Date is being treated by JAXB as a model class instead of a Date class. Therefore it will only marshal public fields and properties, or JAXB annotated fields/properties. If you want it treated as a java.util.Date you can create an XmlAdapter for it.
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class MyDateAdapter extends XmlAdapter<Date, MyDate> {
#Override
public MyDate unmarshal(Date date) throws Exception {
// TODO Add logic to convert Date to MyDate
throw new UnsupportedOperationException();
}
#Override
public Date marshal(MyDate myDate) throws Exception {
return myDate;
}
}
To always have this XmlAdapter applied to your MyDate class you can annotate MyDate with the #XmlJavaTypeAdapter annotation:
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlJavaTypeAdapter(MyDateAdapter.class)
public class MyDate extends Date {
}
UPDATE
What is it that controls whether a class is treated as a model rather
than its contents being included in the marshaling?
For the most part classes not in a standard Java SE package will be treated as a domain object.
Also, when I create that XmlAdapter class, do I just plonk it down
next to MyDate.java in my source directory, or do I need to create a
reference to it somewhere else?
The XmlAdapter is referenced from the #XmlJavaTypeAdapter annotation.

How can I make #XmlAttribute in a special order by using JAXB?

I have XML file which needs 3 attributes in an element. How can make the order of street, zip and city attribute as I wanted?
<address street="Big Street" zip="2012" city="Austin">
</address>
#XmlType(name="Street)
#XmlRootElement(name = "Street")
public class Street {
#XmlAttribute
private String name;
#XmlAttribute
private String type;
... set and get method
}
Anecdotally, the attributes seem to be in reverse order than they are mentioned in code. In my case, I'm using two variables (name & value) and I had to declare them as:
// The inverse order of name & value seems to make them render in XML in name/value order
#XmlAttribute
protected String value;
#XmlAttribute
protected String name;
When the XML is generated, it results in the following:
<attribute name="nameValue" value="valueValue"/>
You can use #XmlAccessorOrder(has predefined values) or #XmlType(Only works for properties) to govern the ordering.
Samples
Edit :
For custom ordering JAXB specification doesnt provide anything, but you can do if your JAXB provider provides you some features.
Found this link where it speaks about ordering using EclipseLink JAXB.

Resources