将 Java 对象转换为 XML 字符串

是的,是的,我知道有很多关于这个话题的问题。但我仍然找不到解决问题的办法。我有一个带属性注释的 Java 对象。例如客户,就像这个例子。我需要它的 String 表示形式。Google 建议为此目的使用 JAXB。但是在所有创建的示例中,XML 文件都被打印到文件或控制台,如下所示:

File file = new File("C:\\file.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();


// output pretty printed
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);


jaxbMarshaller.marshal(customer, file);
jaxbMarshaller.marshal(customer, System.out);

但是我必须使用这个对象并以 XML 格式通过网络发送。所以我想得到一个表示 XML 的 String。

String xmlString = ...
sendOverNetwork(xmlString);

我怎么能这么做?

321279 次浏览

You can marshal it to a StringWriter and grab its string. from toString().

You can use the Marshaler's method for marshaling which takes a Writer as parameter:

marshal(Object,Writer)

and pass it an Implementation which can build a String object

Direct Known Subclasses: BufferedWriter, CharArrayWriter, FilterWriter, OutputStreamWriter, PipedWriter, PrintWriter, StringWriter

Call its toString method to get the actual String value.

So doing:

StringWriter sw = new StringWriter();
jaxbMarshaller.marshal(customer, sw);
String xmlString = sw.toString();

As A4L mentioning, you can use StringWriter. Providing here example code:

private static String jaxbObjectToXML(Customer customer) {
String xmlString = "";
try {
JAXBContext context = JAXBContext.newInstance(Customer.class);
Marshaller m = context.createMarshaller();


m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); // To format XML


StringWriter sw = new StringWriter();
m.marshal(customer, sw);
xmlString = sw.toString();


} catch (JAXBException e) {
e.printStackTrace();
}


return xmlString;
}

Testing And working Java code to convert java object to XML:

Customer.java

import java.util.ArrayList;


import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;




@XmlRootElement
public class Customer {


String name;
int age;
int id;
String desc;
ArrayList<String> list;


public ArrayList<String> getList()
{
return list;
}


@XmlElement
public void setList(ArrayList<String> list)
{
this.list = list;
}


public String getDesc()
{
return desc;
}


@XmlElement
public void setDesc(String desc)
{
this.desc = desc;
}


public String getName() {
return name;
}


@XmlElement
public void setName(String name) {
this.name = name;
}


public int getAge() {
return age;
}


@XmlElement
public void setAge(int age) {
this.age = age;
}


public int getId() {
return id;
}


@XmlAttribute
public void setId(int id) {
this.id = id;
}
}

createXML.java

import java.io.StringWriter;
import java.util.ArrayList;


import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;




public class createXML {


public static void main(String args[]) throws Exception
{
ArrayList<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
Customer c = new Customer();
c.setAge(45);
c.setDesc("some desc ");
c.setId(23);
c.setList(list);
c.setName("name");
JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StringWriter sw = new StringWriter();
jaxbMarshaller.marshal(c, sw);
String xmlString = sw.toString();
System.out.println(xmlString);
}


}

To convert an Object to XML in Java

Customer.java

package com;


import java.util.ArrayList;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;


/**
*
* @author ABsiddik
*/


@XmlRootElement
public class Customer {


int id;
String name;
int age;


String address;
ArrayList<String> mobileNo;




public int getId() {
return id;
}


@XmlAttribute
public void setId(int id) {
this.id = id;
}


public String getName() {
return name;
}


@XmlElement
public void setName(String name) {
this.name = name;
}


public int getAge() {
return age;
}


@XmlElement
public void setAge(int age) {
this.age = age;
}


public String getAddress() {
return address;
}


@XmlElement
public void setAddress(String address) {
this.address = address;
}


public ArrayList<String> getMobileNo() {
return mobileNo;
}


@XmlElement
public void setMobileNo(ArrayList<String> mobileNo) {
this.mobileNo = mobileNo;
}




}

ConvertObjToXML.java

package com;


import java.io.File;
import java.io.StringWriter;
import java.util.ArrayList;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;


/**
*
* @author ABsiddik
*/
public class ConvertObjToXML {


public static void main(String args[]) throws Exception
{
ArrayList<String> numberList = new ArrayList<>();
numberList.add("01942652579");
numberList.add("01762752801");
numberList.add("8800545");


Customer c = new Customer();


c.setId(23);
c.setName("Abu Bakar Siddik");
c.setAge(45);
c.setAddress("Dhaka, Bangladesh");
c.setMobileNo(numberList);


File file = new File("C:\\Users\\NETIZEN-ONE\\Desktop \\customer.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);


jaxbMarshaller.marshal(c, file);// this line create customer.xml file in specified path.


StringWriter sw = new StringWriter();
jaxbMarshaller.marshal(c, sw);
String xmlString = sw.toString();


System.out.println(xmlString);
}


}

Try with this example..

Using ByteArrayOutputStream

public static String printObjectToXML(final Object object) throws TransformerFactoryConfigurationError,
TransformerConfigurationException, SOAPException, TransformerException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XMLEncoder xmlEncoder = new XMLEncoder(baos);
xmlEncoder.writeObject(object);
xmlEncoder.close();


String xml = baos.toString();
System.out.println(xml);


return xml.toString();
}
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;


private String generateXml(Object obj, Class objClass) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(objClass);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StringWriter sw = new StringWriter();
jaxbMarshaller.marshal(obj, sw);
return sw.toString();
}

A convenient option is to use javax.xml.bind.JAXB:

StringWriter sw = new StringWriter();
JAXB.marshal(customer, sw);
String xmlString = sw.toString();

The [reverse] process (unmarshal) would be:

Customer customer = JAXB.unmarshal(new StringReader(xmlString), Customer.class);

No need to deal with checked exceptions in this approach.

Use this function to convert Object to xml string (should be called as convertToXml(sourceObject, Object.class); )-->

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;


public static <T> String convertToXml(T source, Class<T> clazz) throws JAXBException {
String result;
StringWriter sw = new StringWriter();
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
QName qName = new QName(StringUtils.uncapitalize(clazz.getSimpleName()));
JAXBElement<T> root = new JAXBElement<T>(qName, clazz, source);
jaxbMarshaller.marshal(root, sw);
result = sw.toString();
return result;
}

Use this function to convert xml string to Object back --> (should be called as createObjectFromXmlString(xmlString, Object.class))

public static <T> T createObjectFromXmlString(String xml, Class<T> clazz) throws JAXBException, IOException{


T value = null;
StringReader reader = new StringReader(xml);
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
JAXBElement<T> rootElement=jaxbUnmarshaller.unmarshal(new StreamSource(reader),clazz);
value = rootElement.getValue();
return value;
}

Some Generic code to create XML Stirng

object --> is Java class to convert it to XML
name --> is just name space like thing - for differentiate

public static String convertObjectToXML(Object object,String name) {
try {
StringWriter stringWriter = new StringWriter();
JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
QName qName = new QName(object.getClass().toString(), name);
Object root = new JAXBElement<Object>(qName,java.lang.Object.class, object);
jaxbMarshaller.marshal(root, stringWriter);
String result = stringWriter.toString();
System.out.println(result);
return result;
}catch (Exception e) {
e.printStackTrace();
}
return null;
}

I took the JAXB.marshal implementation and added jaxb.fragment=true to remove the XML prolog. This method can handle objects even without the XmlRootElement annotation. This also throws the unchecked DataBindingException.

public static String toXmlString(Object o) {
try {
Class<?> clazz = o.getClass();
JAXBContext context = JAXBContext.newInstance(clazz);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true); // remove xml prolog
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // formatted output


final QName name = new QName(Introspector.decapitalize(clazz.getSimpleName()));
JAXBElement jaxbElement = new JAXBElement(name, clazz, o);


StringWriter sw = new StringWriter();
marshaller.marshal(jaxbElement, sw);
return sw.toString();


} catch (JAXBException e) {
throw new DataBindingException(e);
}
}

If the compiler warning bothers you, here's the templated, two parameter version.

public static <T> String toXmlString(T o, Class<T> clazz) {
try {
JAXBContext context = JAXBContext.newInstance(clazz);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true); // remove xml prolog
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // formatted output


QName name = new QName(Introspector.decapitalize(clazz.getSimpleName()));
JAXBElement jaxbElement = new JAXBElement<>(name, clazz, o);


StringWriter sw = new StringWriter();
marshaller.marshal(jaxbElement, sw);
return sw.toString();


} catch (JAXBException e) {
throw new DataBindingException(e);
}
}

Here is a util class for marshaling and unmarshaling objects. In my case it was a nested class, so I made it static JAXBUtils.

import javax.xml.bind.JAXB;
import java.io.StringReader;
import java.io.StringWriter;


public class JAXBUtils
{
/**
* Unmarshal an XML string
* @param xml     The XML string
* @param type    The JAXB class type.
* @return The unmarshalled object.
*/
public <T> T unmarshal(String xml, Class<T> type)
{
StringReader reader = new StringReader(xml);
return javax.xml.bind.JAXB.unmarshal(reader, type);
}


/**
* Marshal an Object to XML.
* @param object    The object to marshal.
* @return The XML string representation of the object.
*/
public String marshal(Object object)
{
StringWriter stringWriter = new StringWriter();
JAXB.marshal(object, stringWriter);
return stringWriter.toString();
}
}

Underscore-java can construct XML string with help of a builder.

    class Customer {
String name;
int age;
int id;
}
Customer customer = new Customer();
customer.name = "John";
customer.age = 30;
customer.id = 12345;


String xml = U.objectBuilder().add("customer", U.objectBuilder()
.add("name", customer.name)
.add("age", customer.age)
.add("id", customer.id)).toXml();


// <?xml version="1.0" encoding="UTF-8"?>
//    <customer>
//      <name>John</name>
//      <age number="true">30</age>
//      <id number="true">12345</id>
//    </customer>

Below is one example of Java Class, different set of annotations to generate xml, CDATA and JaxB code to generate XML.

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name="customer")
public class Customer {
   

@XmlElement(name = "first-name")
String firstName;
@XmlElement(name = "last-name")
String lastName;
   

@XmlElement(name= "customer-address")
private Address address;
   

@XmlElement(name= "bio")
@XmlJavaTypeAdapter(AdapterCDATA.class)
private Biography bio;
}




@XmlAccessorType(XmlAccessType.FIELD)
public class Address {
   

@XmlElement(name = "house-number")
String houseNumber;
@XmlElement(name = "address-line-1")
String addLine1;
   

@XmlElement(name = "address-line-2")
String addLine2;
   

}


 

Adaptor Class

    public class AdaptorCDATA extends XmlAdapter<String, String> {


@Override
public String marshal(String arg0) throws Exception {
return "<![CDATA[" + arg0 + "]]>";
}
@Override
public String unmarshal(String arg0) throws Exception {
return arg0;
}
}

JAXB code to generat XML

  public String xmlStringForCustomer(Customer customer) {
 

JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    

StringWriter writer = new StringWriter();
marshaller.marshal(customer,sw);
return sw.toString();
}

Above Code will generate an xml like below

<customer>
<first-name></first-name>
<last-name></last-name>
<customer-address>
<house-number></house-number>
<address-line-1></address-line-1>
<address-line-2></address-line-2>
</customer-address>
<bio>
<![CDATA[ **bio data will come here**]]>
</bio>
< /customer>