CSV作为XML元素的文本节点

时间:2013-06-15 02:41:54

标签: java xml csv jaxb xml-serialization

将CSV格式的数据放入xml元素中有什么优缺点?

我必须使用矩阵数据字段将java中的对象序列化为xml。我放弃了使用Jaxb数据绑定的想法;包含集合的泛型和集合太难以处理。

我想到了矩阵的简单模式,但由于我还必须实现矩阵序列化为CSV,为什么不将CSV字符串转换为元素中的文本节点?它还会使文件变小。

你能想到反对这个想法的论据吗?

我应该在此元素中添加类似csv mimetype的内容吗?

编辑:这是我选择的解决方案。它使用Super-CSV。需要枚举,因为泛型类型在运行时被擦除。主xml文件将引用csv文件。

static public enum SerializableType{INTEGER,DOUBLE,...};

@SuppressWarnings("unchecked")
public static <T> Matrix<T> fromCSV(InputStream in, CsvPreference pref, SerializableType t)
{

    Matrix<T> o = new Matrix<T>();
    // Super-csv class
    CsvListReader csv_reader = new CsvListReader(new InputStreamReader(in), pref);

    Integer n = null;
    try {
        List<String> l = csv_reader.read(); 
        n = l.size(); o.n = n;

        int i=0;

        while(l!=null)
        {
            o.appendRow();
            T val;
            for(int j=0;j<n;j++)
            {
                switch(t)
                {
                case INTEGER:
                    val = (T)Integer.valueOf(Integer.parseInt(l.get(j)));
                    break;
                case DOUBLE:
                    val = (T)Double.valueOf(Double.parseDouble(l.get(j)));
                    break;
                case <...>

                default:
                    throw new IllegalArgumentException();
                }
                o.set(i,j, val);
            }
            i++;

            l = csv_reader.read();
        }

        csv_reader.close();

    } catch (IOException e) {

        e.printStackTrace();
    }

    return o;
}


public static<T> void toCSV(Matrix<T> m, CsvListWriter csv_writer, SerializableType t)
{

    try {

        for(int i=0;i<m.rowCount();i++)
        {
            ArrayList<String> l = new ArrayList<String>();

            for(int j=0;j<m.columnCount();j++)
            {
                if(m.get(i,j)==null)
                {
                    l.add(null);
                }
                else{
                    switch(t)
                    {
                    case INTEGER:
                        l.add(Integer.toString((Integer)m.get(i,j)));
                        break;
                    case DOUBLE:
                        l.add(Double.toString((Double)m.get(i,j)));
                        break;
                    case 
                        <...>

                    default:
                        throw new IllegalArgumentException();
                    };
                }
            }

            csv_writer.write(l);
        }

        csv_writer.flush();
        csv_writer.close();
    } catch (IOException e) {

        e.printStackTrace();
    }
}

2 个答案:

答案 0 :(得分:1)

XML是构建某种信息的一种很好的格式,但除了XML库的技术限制之外,对于像Matrix这样的其他人来说是一种痛苦,因为你不想让所有这些可怕的角度混乱干净的表格表示括号无处不在,您经常需要基于拆分进行快速解析。

在这种情况下你应该避免使用&#34;如果你拥有的只是一把锤子,那么一切看起来都像钉子一样。综合症,您需要另一种能够自然处理表格数据的表示:CSV。

因此,结合两种格式优势的想法是正确的想法:需要结构化的数据的XML,表格数据的CSV。

对于MIME类型,如果只有你的应用程序将处理该文件,你真的不需要指定它,但添加一个真的不会花费很多;但我不知道是否存在任何标准属性,除非像&#34; xsi:type =&#34; CSV&#34; &#34;。

PS:我在不同的背景下写过关于上述综合症的文章:http://pragmateek.com/if-all-you-have-is-a-hammer/:)

答案 1 :(得分:1)

XML模式允许您定义一个集合类型,其中项目由空格分隔。

<xs:list itemType="xs:int"/>

以下是如何在JAXB中利用它来表示矩阵的完整示例。

Java模型(根)

我们将使用2维int数组来表示矩阵。我们将使用XmlAdapter来获取非默认数组表示(请参阅:JAXB & java.util.Map

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement
public class Root {

    private int[][] matrix;

    @XmlJavaTypeAdapter(MatrixAdapter.class)
    public int[][] getMatrix() {
        return matrix;
    }

    public void setMatrix(int[][] matrix) {
        this.matrix = matrix;
    }

}

XmlAdapter(MatrixAdapter)

当您使用int[]注释@XmlValue时,XML表示将是以空格分隔的文本。

import java.util.*;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlAdapter;

public class MatrixAdapter extends XmlAdapter<MatrixAdapter.AdaptedMatrix, int[][]>{

    public static class AdaptedMatrix {
        @XmlElement(name="row")
        public List<AdaptedRow> rows;
    }

    public static class AdaptedRow {

        @XmlValue
        public int[] row;
    }

    @Override
    public AdaptedMatrix marshal(int[][] matrix) throws Exception {
        AdaptedMatrix adaptedMatrix = new AdaptedMatrix();
        adaptedMatrix.rows = new ArrayList<AdaptedRow>(matrix.length);
        for(int[] row : matrix) {
            AdaptedRow adaptedRow = new AdaptedRow();
            adaptedRow.row = row;
            adaptedMatrix.rows.add(adaptedRow);
        }
        return adaptedMatrix;
    }

    @Override
    public int[][] unmarshal(AdaptedMatrix adaptedMatrix) throws Exception {
        List<AdaptedRow> adaptedRows = adaptedMatrix.rows;
        int[][] matrix = new int[adaptedRows.size()][];
        for(int x=0; x<adaptedRows.size(); x++) {
            matrix[x] = adaptedRows.get(x).row;
        }
        return matrix;
    }

}

演示代码

下面是一些可以运行的演示代码,以证明一切正常:

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum17119708/input.xml");
        Root root = (Root) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

<强> input.xml中/输出

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <matrix>
      <row>1 2 3 4</row>
      <row>5 6 7 8</row>
   </matrix>
</root>

<强> input.xml中/输出

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <matrix>
        <row>1 2 3</row>
        <row>4 5 6</row>
        <row>7 8 9</row>
    </matrix>
</root>
相关问题