2

将 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();
    }
}
4

2 回答 2

1

XML 是一种很好的格式来构建某种信息,但对于矩阵等其他信息来说是一种痛苦,超出了 XML 库的技术限制,因为你不想用所有这些可怕的尖括号将你干净的表格表示弄乱,而且你经常想要基于拆分的快速解析。

在这种情况下,您应该避免“如果您只有一把锤子,一切看起来都像钉子”综合症,您需要另一种可以自然处理表格数据的表示:CSV。

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

至于 MIME 类型,如果只有您的应用程序将处理文件,您确实不需要指定它,但添加一个确实不会花费很多;但我不知道是否存在任何标准属性,除了“ xsi:type="CSV" ”之类的东西。

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

于 2013-06-15T16:18:50.143 回答
1

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

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

下面是一个完整示例,说明如何在 JAXB 中利用它来表示矩阵。

Java 模型(根)

我们将使用一个二维 int 数组来表示输出矩阵。我们将使用 anXmlAdapter来获取非默认数组表示(请参阅: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(矩阵适配器)

当您int[]@XmlValueXML 表示注释时,将是空格分隔的文本。

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);
    }

}

输入.xml/输出

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

输入.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>
于 2013-06-17T14:58:55.767 回答