I have been trying to convert xml string to Java object.
There is a root tag of TV . There are multiple fields inside this but I want the whole content as one String.
#XmlRootElement(name = "TV")
#XmlAccessorType(XmlAccessType.FIELD)
public class TV {
#XmlElement
public String details;
public String getDetails() {
return details;
}
public void setDetails(String details) {
this.details = details;
}
#Override
public String toString() {
return "TV [details=" + details + "]";
}
}
public class XMLtoJavaObject {
public static void main(String[] args) {
String xmlString = "<TV version=\"0.91fn\"><channel><title>Friends</title><link>https://www.imdb.com/title/tt0108778/</link><season>2</season></channel></TV>";
JAXBContext jaxbContext;
try {
jaxbContext = JAXBContext.newInstance(TV.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
TV tv = (TV) jaxbUnmarshaller.unmarshal(new StringReader(xmlString));
System.out.println("TV" + tv);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
Output:
TV [details=null]
I am not getting whole nested xml as String.
Can somebody help me what I am missing?
Thanks in advance
Try this:
TV class:
#XmlRootElement(name = "TV")
#XmlAccessorType(XmlAccessType.FIELD)
public class TV {
#XmlElement
private Channel channel;
public Channel getChannel() {
return channel;
}
public void setChannel(Channel channel) {
this.channel = channel;
}
#Override
public String toString() {
return "TV [channel=" + channel + "]";
}
}
Channel class:
#XmlAccessorType(XmlAccessType.FIELD)
public class Channel {
#XmlElement
private String title;
private String link;
private String season;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public String getSeason() {
return season;
}
public void setSeason(String season) {
this.season = season;
}
#Override
public String toString() {
return "Channel [title=" + title + ", link=" + link + ", season=" + season + "]";
}
}
Output:
TVTV [channel=Channel [title=Friends, link=https://www.imdb.com/title/tt0108778/, season=2]]
And now You can get Your details using Java as You want e.g.:
tv.getChannel().getTitle();
Another answser:
TV class:
#XmlRootElement(name = "TV")
#XmlAccessorType(XmlAccessType.FIELD)
public class TV {
#XmlAnyElement
private org.w3c.dom.Element channel;
#Override
public String toString() {
return "TV [channel=" + channel + "]";
}
public org.w3c.dom.Element getChannel() {
return channel;
}
public void setChannel(org.w3c.dom.Element channel) {
this.channel = channel;
}
}
Then You get text content like this:
System.out.println("text: " + tv.getChannel().getTextContent());
Output:
text: Friendshttps://www.imdb.com/title/tt0108778/2
Note that it is all texts just concatenated.
But having an Element You can iterate recursively through all children and print them together with tag names and text values.
Here is a sample recursive method:
channel field name needs to be a Node type:
....
private org.w3c.dom.Node channel;
....
private static String build(Node element) {
final String result;
if (element instanceof Text) {
result = element.getNodeValue();
} else {
final StringBuilder sb = new StringBuilder();
sb.append("<").append(element.getNodeName()).append(">");
for (int i = 0; i < element.getChildNodes().getLength(); i++) {
final Node child = element.getChildNodes().item(i);
sb.append(build(child));
}
sb.append("</").append(element.getNodeName()).append(">");
result = sb.toString();
}
return result;
}
Called like this:
System.out.println(build(tv.getChannel()));
Output:
<channel><title>Friends</title><link>https://www.imdb.com/title/tt0108778/</link><season>2</season></channel>
Related
I've made an RESTful api that returns following simple XML:
<!-- language: lang-xml -->
<?xml version="1.0" encoding="utf-8"?>
<GoldPriceArray>
<GoldPrice>
<Date>2020-06-15</Date>
<Price>219.01</Price>
</GoldPrice>
<GoldPrice>
<Date>2020-06-16</Date>
<Price>216.73</Price>
</GoldPrice>
</GoldPriceArray>
I'm trying to unmarchall Date and Price but cannot get into nested elements - my code returns NullPointerException on unmarchaller() method. Here's my code
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "GoldPriceArray")
public class GoldRates {
private List<GoldRate> goldRateList;
private String goldValue;
public GoldRates() {}
public GoldRates(String goldPrice, List<GoldRate> goldRateList) {
this.goldRateList = goldRateList;
this.goldValue = goldPrice;
}
#XmlElement
public List<GoldRate> getList() {
return goldRateList;
}
public void setList(ArrayList<GoldRate> goldRateList) {
this.goldRateList = goldRateList;
}
#XmlElement
public String getPrice() {
return goldValue;
}
public void setPrice(String goldPrice) {
this.goldValue = goldPrice;}
public class GoldRate {
#XmlElement(name = "Date")
private String dateOfPrice;
#XmlElement(name = "Price")
private String price;
public GoldRate() {
}
public GoldRate(String date, String value) {
this.dateOfPrice = date;
this.price = value;
}
public String getDate() {
return dateOfPrice;
}
public void setDate(String date) {
this.dateOfPrice = date;
}
public String getValue() {
return price;
}
public void setValue(String value) {
this.price = value;
}
#Override
public String toString() {
return "Date: " + dateOfPrice + " value: " + price;
}
}
Unmarchalling method that returns NullPointerException on System.out.println()
public void unmarshaller(String xml) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(GoldRates.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
GoldRates goldRates = (GoldRates) jaxbUnmarshaller.unmarshal(new StringReader(xml));
System.out.println(goldRates.getList().get(0).getValue() + " " + goldRates.getList().get(0).getDate());
} catch (JAXBException e) {
e.printStackTrace();
}
return null;
}
Any hints on this one? I'm really stuck.
Just found solution:
private List<GoldRate> goldRateList
should be named exactly the same as an element of XML that it refers to, so the proper one is:
private List<GoldRate> GoldPrice
I have json file from which I parse json objects to java objects using Gson library. The next step is to create main class in which with the help of Apache POI prepared docx file is read, some changes were made in the text and new document with changes is created. The problem I faced is that the text which should be changed need to be variable(from json file). I mean that "name" and "testName" both should be variables or methods, so I can call them from text.contains. Can you show my mistake and the right way to do the task. Thanks in advance.
Here is my code `
public class main {
public static void gson() {
Gson gson = new Gson();
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("jsonn.json"));
Result result = gson.fromJson(br, Result.class);
if (result != null) {
result.getName();
result.getLastname();
System.out.println(result.getName());
System.out.println(result.getLastname());
for (Phone p : result.getPhones()) {
p.getType();
p.getNum();
System.out.println(p.getType() + ": " + p.getNum());
// System.out.println(p.getType()+" : "+p.getNum());
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}}
public class Result {
#SerializedName("name")
#Expose
private String name;
#SerializedName("lastname")
#Expose
private String lastname;
#SerializedName("phones")
#Expose
private List<Phone> phones = null;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public List<Phone> getPhones() {
return phones;
}
public void setPhones(List<Phone> phones) {
this.phones = phones;
}}
public class Phone {
#SerializedName("name")
#Expose
private String name;
#SerializedName("lastName")
#Expose
private String lastName;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#SerializedName("num")
#Expose
private String num;
#SerializedName("type")
#Expose
private String type;
public String getNum() {
return num;
}
public void setNum(String num) {
this.num = num;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}}
public class Read {
public static void main(String[] args) throws InvalidFormatException,
IOException {
main.gson();
XWPFDocument doc = new XWPFDocument(OPCPackage.open("Шаблон.docx"));
Result res = new Result();
String replaceName = res.getName();
for (XWPFParagraph p : doc.getParagraphs()) {
List<XWPFRun> runs = p.getRuns();
if (runs != null) {
for (XWPFRun r : runs) {
String text = r.getText(0);
if (text != null && text.contains("name")) {
text = text.replace("name", "Alex");
r.setText(text, 0);
}
}
}
}
for (XWPFTable tbl : doc.getTables()) {
for (XWPFTableRow row : tbl.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
for (XWPFParagraph p : cell.getParagraphs()) {
for (XWPFRun r : p.getRuns()) {
String text = r.getText(0);
if (text != null && text.contains("name")) {
text = text.replace("name", "Alex");
r.setText(text, 0);
}
}
}
}
}
}
doc.write(new FileOutputStream("Пример.docx"));
}}
`
Here is json file:
{
"name":"testName",
"lastname":"testLastName",
"phones":[
{
"num":"9000000",
"type":"mobile"
},
{
"num":"1000000",
"type":"home"
} ]}
Trying to convert a POJO to a Json representation , my output is quite surprising : empty !
Here the POJO class :
public class AccountDTO extends BasicDBObject {
/**
*
*/
public static final String COLLECTION_NAME = "account-data";
private static final long serialVersionUID = 1L;
private String customerFirstName;
private String customerLastName;
private long customerId;
private String IBAN;
private float balance;
private String accountCurrency;
public AccountDTO(Account account, Customer customer) {
super();
this.customerFirstName = customer.getFirstname();
this.customerLastName = customer.getLastname();
this.customerId = customer.getCustomerId();
this.IBAN = account.getIBAN();
this.balance = account.getBalance();
this.accountCurrency = account.getAccountCurrency();
}
public String getCustomerName() {
return customerFirstName;
}
public void setCustomerName(String customerName) {
this.customerFirstName = customerName;
}
public String getCustomerLastName() {
return customerLastName;
}
public void setCustomerLastName(String customerLastName) {
this.customerLastName = customerLastName;
}
public long getCustomerId() {
return customerId;
}
public void setCustomerId(long customerId) {
this.customerId = customerId;
}
public String getIBAN() {
return IBAN;
}
public void setIBAN(String iBAN) {
IBAN = iBAN;
}
public float getBalance() {
return balance;
}
public void setBalance(float balance) {
this.balance = balance;
}
public String getCustomerFirstName() {
return customerFirstName;
}
public void setCustomerFirstName(String customerFirstName) {
this.customerFirstName = customerFirstName;
}
public String getAccountCurrency() {
return accountCurrency;
}
public void setAccountCurrency(String accountCurrency) {
this.accountCurrency = accountCurrency;
}
#Override
public String toString() {
return "AccountDTO [customerFirstName=" + customerFirstName + ", customerLastName=" + customerLastName
+ ", customerId=" + customerId + ", IBAN=" + IBAN + ", balance=" + balance + ", accountCurrency="
+ accountCurrency + "]";
}
}
The converter :
public abstract class AccountDTODigester {
public static String digestJavaToJson(AccountDTO dto){
Gson gson = new Gson();
String json = gson.toJson(dto);
return json;
}
}
Code with jackson :
public abstract class AccountDTODigester {
public static String digestJavaToJson(AccountDTO dto) throws JsonProcessingException{
ObjectMapper mapper = new ObjectMapper();
String jsonInString = new String();
jsonInString = mapper.writeValueAsString(dto);
return jsonInString;
}
}
And finnaly the runner :
public class DAOTest {
AccountDTO accountDTO;
#Before
public void initialize(){
Account account = new Account("FRkk BBBB BGGG GGCC CCCC CCCC CKK", 0, "euro");
Customer customer = new Customer("XXXXXX", "YYYYYY", 1, account);
this.accountDTO = new AccountDTO(account, customer);
}
#Test
public void toJson(){
Assert.assertNotEquals(AccountDTODigester.digestJavaToJson(accountDTO),new String("{}"));
}
Console output :
AccountDTO [customerFirstName=XXXXXX, customerLastName=YYYYYY, customerId=1, IBAN=FRkk BBBB BGGG GGCC CCCC CCCC CKK, balance=0.0, accountCurrency=euro]
{}
When I run the test, my json string is { }and my test is mark as failed.
Gson seems to ver very easy to use, I don't understand why I got this empty Json instead a String filled with a json representation of my AccountDTO object
Ok I found solution :
My JSON was null because extends BasicDBObject , the serialization seems to be jammed by this.
Still looking for a better explication, but now my json is ok.
I have an xml input as below
<Confirmations>
<SystemConf>
<SysCnf>
<MessageId>1</MessageId>
</SysCnf>
<SysCnf>
<MessageId>2</MessageId>
</SysCnf>
</SystemConf>
</Confirmations>
and these are my classes
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "Confirmations")
public class Confirmations
{
#XmlElementWrapper(name = "SystemConf")
#XmlElement(name = "SysCnf")
private List<SystemConfirmation> systemConfirmations = null;
public List<SystemConfirmation> getSystemConfirmations()
{
return systemConfirmations;
}
public void setSystemConfirmations(List<SystemConfirmation> systemConfirmations)
{
this.systemConfirmations = systemConfirmations;
}
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "SysCnf")
public class SystemConfirmation
{
#XmlElement(name = "MessageId")
private String messageId;
public void setMessageId(String messageId)
{
this.messageId = messageId;
}
public String getMessageId()
{
return messageId;
}
#XmlAnyElement(value = SysConfXmlStringHandler.class)
private String xml;
public String getXml()
{
return xml;
}
}
public class SysConfXmlStringHandler implements DomHandler<String, StreamResult>
{
private static final String SYSCONF_START_TAG = "<SycCnf>";
private static final String SYSCONF_END_TAG = "</SysCnf>";
private StringWriter xmlWriter = new StringWriter();
#Override
public StreamResult createUnmarshaller(ValidationEventHandler errorHandler)
{
return new StreamResult(xmlWriter);
}
#Override
public String getElement(StreamResult rt)
{
String xml = rt.getWriter().toString();
System.out.println(xml);
int beginIndex = xml.indexOf(SYSCONF_START_TAG) + SYSCONF_START_TAG.length();
int endIndex = xml.indexOf(SYSCONF_END_TAG);
return xml.substring(beginIndex, endIndex);
}
#Override
public Source marshal(String n, ValidationEventHandler errorHandler)
{
try
{
String xml = SYSCONF_START_TAG + n.trim() + SYSCONF_END_TAG;
StringReader xmlReader = new StringReader(xml);
return new StreamSource(xmlReader);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
}
Question
In the xml field of the SystemConfirmation class I want the whole xml of that particular SystemConfirmation block xmml element, which would be below
<SysCnf>
<MessageId>1</MessageId>
</SysCnf>
Does anyone know how to achieve this? I tried the above code but I was only getting MessageId block in the xml and if I add multiple fields in SystemConfirmation than I only get the first one.
I want to serialize a object hierarchy including a list of objects which derive from the base class 'Thing'. This works fine, including deserialization - but XML-Simple insists in writing an attribute which specifies the actual used Java-class
when I create a xml file with the java code below, the content is like this:
<example1>
<things>
<fruit class="com.mumpitz.simplexmltest.Apple" id="17">
<sugar>212</sugar>
</fruit>
<fruit class="com.mumpitz.simplexmltest.Orange" id="25" weight="11.2"/>
</things>
</example1>
but this is not what I want.
I'd like to have
<example1>
<things>
<apple id="17">
<sugar>212</sugar>
</apple>
<orange id="25" weight="11.2"/>
</things>
</example1>
'apple' and 'orange' elements without a class attribute, not 'fruit' with such an attribute. Is this possible?
(The second xml complies to a existing schema; adding extra attributes is not an option)
Here's the code:
package com.mumpitz.simplexmltest;
import java.io.File;
import java.util.ArrayList;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
class Fruit {
#Attribute(name = "id")
protected final int id;
Fruit(
#Attribute(name = "id")
int id) {
this.id = id;
}
int getObjectId() {
return id;
}
}
#Root
class Apple extends Fruit {
private final int sugar;
#Element(type = Fruit.class)
public Apple(
#Attribute(name = "id")
int id,
#Element(name = "sugar")
int sugar) {
super(id);
this.sugar = sugar;
}
#Element(name = "sugar")
public int getSugar() {
return this.sugar;
}
#Override
public String toString() {
return "id: " + id + ", sugar: " + sugar;
}
}
#Root
class Orange extends Fruit {
#Attribute
public double weight;
public Orange(
#Attribute(name = "id")
int id) {
super(id);
}
#Override
public String toString() {
return "id: " + id + ", weight: " + weight;
}
}
#Root
public class Example1 {
#ElementList
public ArrayList<Fruit> things = new ArrayList<Fruit>();
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("things:\n");
for (int i=0; i<things.size(); i++) {
sb.append(" " + things.get(i).toString() + "\n");
}
return sb.toString();
}
//////////////////////////////////
static Example1 createDummy() {
Example1 d = new Example1();
d.things.add(new Apple(17, 212));
Orange or = new Orange(25);
or.weight = 11.2;
d.things.add(or);
return d;
}
static String msg;
static Example1 res;
static public String getMessage() {
String m = msg;
msg = null;
return m;
}
static public boolean write(String path) {
Serializer serializer = new Persister();
Example1 example = Example1.createDummy();
File result = new File(path);
try {
serializer.write(example, result);
} catch (Exception e) {
e.printStackTrace();
msg = e.getMessage();
return false;
}
return true;
}
static public boolean read(String path) {
Serializer serializer = new Persister();
File source = new File(path);
try {
res = serializer.read(Example1.class, source);
} catch (Exception e) {
e.printStackTrace();
msg = e.getMessage();
return false;
}
return true;
}
public static Object getResult() {
return res;
}
}
some hours later I found the solution. You simply have to
Read the manual
Use the #ElementListUnion annotation
package com.mumpitz.simplexmltest;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.ElementListUnion;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
// the base class
#Element
class Thing {
static int count=0;
Thing() {
this.id = ++count;
}
#Attribute
protected int id;
public int getId() {
return id;
}
}
// first derived class
#Element
class Car extends Thing {
#Attribute
private String name;
Car(#Attribute(name="name") String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public String toString() {
return "ID: " + id + " Car: " + name;
}
}
// second derived class
#Element
class House extends Thing {
#Attribute
private int price;
House(#Attribute(name="price") int price) {
this.price = price;
}
public int getPrice() {
return this.price;
}
#Override
public String toString() {
return "ID: " + id + " House: " + price;
}
}
// a class with a list of base class instances
#Root(name="ListOfThings")
public class Example4 {
// specify the derived classes used in the list
#ElementListUnion({
#ElementList(entry="house", inline=true, type=House.class),
#ElementList(entry="car", inline=true, type=Car.class)
})
private ArrayList<Thing> list = new ArrayList<Thing>();
public void add(Thing t) {
list.add(t);
}
public List<Thing> getProperties() {
return list;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Example4 contains " + list.size() + " elements:\n");
for (Thing t : list) {
sb.append(" " + t.toString() + "\n");
}
return sb.toString();
}
//////////////////////////////////
// test code
//////////////////////////////////
static String msg;
static Example4 res;
static public String getMessage() {
String m = msg;
msg = null;
return m;
}
static private Example4 createDummy() {
Example4 d = new Example4();
d.add(new Car("Mercedes"));
d.add(new House(34000000));
d.add(new Car("VW"));
d.add(new House(230000));
return d;
}
//////////////////////////////////
// serialize / deserialize
//////////////////////////////////
static public boolean write(String path) {
Serializer serializer = new Persister();
File result = new File(path);
Example4 example = Example4.createDummy();
try {
serializer.write(example, result);
} catch (Exception e) {
e.printStackTrace();
msg = e.getMessage();
return false;
}
return true;
}
static public boolean read(String path) {
Serializer serializer = new Persister();
File source = new File(path);
try {
res = serializer.read(Example4.class, source);
} catch (Exception e) {
e.printStackTrace();
msg = e.getMessage();
return false;
}
return true;
}
public static Object getResult() {
return res;
}
}