【问题标题】:CSV as text node of an XML elementCSV 作为 XML 元素的文本节点
【发布时间】:2013-06-15 02:41:53
【问题描述】:

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

【问题讨论】:

  • 在阅读了一些简洁的 w3c 规范(哎呀,这伤害了我的大脑......)和一些维基百科文章之后,我想我会使用 jar 和 XInclude 的组合。我将使用 mimetype application/csv 将 csv 文件的 jar-archive-relative 路径放在一些 xml 属性(我将其命名为 type)中。必须序列化的主要类型的成员数据字段对象将位于 jar 中它们自己的 xml 文件中,主文件将包含它们。

标签: java xml csv jaxb xml-serialization


【解决方案1】:

XML 是一种构建某种信息的好格式,但对于矩阵等其他信息来说却是一种痛苦,超出了 XML 库的技术限制,因为您不想在所有这些可怕的尖括号中使干净的表格表示混乱并且您经常希望基于拆分进行快速解析。

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

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

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

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

【讨论】:

    【解决方案2】:

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

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

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

    Java 模型(根)

    我们将使用一个二维 int 数组来表示 out 矩阵。我们将使用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)

    当您使用@XmlValue 注释int[] 时,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/Output

    <?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/Output

    <?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>
    

    【讨论】:

    • 对于简单的数组,还可以,但对于泛型集合,你必须多写 10 倍的代码。
    • ...您无法将 xml 文件导入 excel。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 1970-01-01
    相关资源
    最近更新 更多