XStream wrongly transform the single underscore '_' to duplicated underscore in field name

38 views Asked by At

I would like to use XStream to do the XML transformation from POJO. It seems that by using XStream, it would wrongly convert the '_' to '__' in the field name. Below is the code I am using in my program. I tried to implement an CustomizedStaxDriver but it seems not work at all. Would anyone please give advice to me to solve such problem. Thank you very much.

Problem: After using XStream, name_cd becomes <name__cd> , '_' becomes '__'

CustomizedStaxDriver.java

import java.util.ArrayList;
import java.util.List;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.naming.NameCoder;
import com.thoughtworks.xstream.io.xml.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CustomizedStaxDriver extends StaxDriver
{

    private static final Logger logger = LoggerFactory.getLogger(CustomizedStaxDriver.class);

    /**The list that contains the field names that would contain a CDATA in the xml.*/
    private static final List CDATA_FIELDS;

    static
    {
        CDATA_FIELDS = new ArrayList();

        //add cdata field names.eg:cdataField
        CDATA_FIELDS.add("cdataField");
        CDATA_FIELDS.add("description");
    }

    public CustomizedStaxDriver() {
        super(new XmlFriendlyNameCoder());
    }

    @Override
    public StaxWriter createStaxWriter(XMLStreamWriter out,
                                       boolean writeStartEndDocument) throws XMLStreamException
    {
        final XMLStreamWriter writer = out;
        return new StaxWriter(getQnameMap(), out, writeStartEndDocument,
                isRepairingNamespace())
        {
            boolean cdata = false;

            @Override
            public void startNode(String name)
            {
                //logger.info("startNode(1):"+name);
                String fixedName = fixNodeName(name);
                super.startNode(fixedName);
                cdata = CDATA_FIELDS.contains(name);
            }

            @Override
            public void startNode(String name, Class clazz) {
                //logger.info("startNode(2):"+name);
                String fixedName = fixNodeName(name);
                super.startNode(fixedName, clazz);
            }


            private String fixNodeName(String name) {
                //return name.replace("_", "__");
                //return super.encodeNode(name);
                return name;
            }


            @Override
            public void setValue(String value)
            {
                if (cdata)
                {
                    try
                    {
                        writer.writeCData(value);
                    }
                    catch (XMLStreamException e)
                    {
                        e.printStackTrace();
                    }
                }else{
                    super.setValue(value);
                }

            }

        };
    }

}

Item.java

import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;

@Data
@XStreamAlias("item")
public class Item {

    @XStreamAlias("name_cd")
    private String nameCd;

    @XStreamAlias("description")
    //@XStreamConverter(CDataConverter.class)
    private String description;

    public Item(String nameCd, String description) {
        this.nameCd = nameCd;
        this.description = description;
    }

}

Main Method Call

        XStream xstream2 = new XStream(new CustomizedStaxDriver());
        Item item = new Item("Item Name", "Item Description");
        xstream2.processAnnotations(Item.class);
        String dataXml2 = xstream2.toXML(item);
        System.out.println("GG:"+dataXml2);

Result

<?xml version='1.0' encoding='UTF-8'?><item><name__cd>Item Name</name__cd><description><![CDATA[Item Description]]></description></item>
0

There are 0 answers