2013-06-15 5 views
2

Каковы преимущества и недостатки вставки CSV-форматированных данных внутри элемента xml?CSV как текстовый узел XML-элемента

Я должен сериализовать объекты в java с полем данных матрицы в xml. Я отказался от идеи использования привязки данных с Jaxb; дженерики и коллекции, содержащие коллекции, слишком много для борьбы.

Я думал о простой схеме для моей матрицы, но так как мне также придется реализовывать сериализацию матриц в CSV, почему бы просто не сбросить CSV-строку в качестве текстового узла в элементе? Это также сделает файлы немного меньше.

Можете ли вы представить аргументы против этой идеи?

Должен ли я добавить что-то вроде csv mimetype к этому элементу?

EDIT: Вот решение, которое я выбрал. Он использует 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(); 
    } 
} 
+0

После прочтения бит некоторых скупых w3c спецификации (Уче, что болеет мой мозг ...) и несколько статей Википедии, я думаю, что я буду использовать комбинацию баночки и XInclude , Я положу пути, связанные с jar-архивом, в файлы csv в некотором атрибуте xml (я назову его тип) с помощью приложения mimetype/csv. Объекты полей данных элемента основного типа, которые должны быть сериализованы, будут находиться в собственном XML-файле в банке с основным файлом, который будет их включать. –

ответ

1

XML хороший формат для структурирования своего рода информации, но боли для других, как матрица, помимо технических ограничений библиотек XML, потому что вы не хотите загромождать чистое представление табличного со всеми этими ужасные угловые скобки повсюду, и вам часто требуется быстрый синтаксический анализ на основе раскола.

В этом случае вам следует избегать «если все, что у вас есть, это молот, все выглядит как гвоздь», вам нужно другое представление, которое, естественно, может обрабатывать табличные данные: CSV.

Итак, ваша идея объединить преимущества обоих форматов - правильная идея: XML для данных, которые нуждаются в структурировании, CSV для табличных данных.

Что касается типа MIME, если только ваше приложение будет иметь дело с файлом, вам действительно не нужно его указывать, но добавление одного действительно не стоит дорого; но я не знаю, существуют ли какие-либо стандартные атрибуты, кроме, может быть, что-то вроде «xsi: type =« CSV »».

PS: Я написал о вышеупомянутом синдроме в другом контексте: http://pragmateek.com/if-all-you-have-is-a-hammer/ :)

+0

Я бы поднял тебя, но у меня недостаточно очков. –

1

XML-схема позволяет определить тип коллекции, где элементы разделены пробелом.

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

Ниже приведен полный пример того, как вы могли бы использовать это в JAXB для представления матрицы.

Java Model (Root)

Мы будем использовать 2 одномерный целочисленный массив для представления из матрицы. Мы будем использовать 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; 
    } 

} 

Demo Code

Ниже некоторые демо-код, который вы можете запустить, чтобы доказать, что все работает:

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> 
+0

Для простых массивов это может быть нормально, но для общей коллекции вам придется писать в 10 раз больше кода. –

+0

... и вы не можете импортировать свой XML-файл в excel. –

Смежные вопросы