Сортировка XML в Java - PullRequest
       65

Сортировка XML в Java

6 голосов
/ 27 мая 2010

Здравствуйте, у меня есть XML, похожий на приведенный ниже, который нужно было отсортировать по полю даты.

<root> 
    <Node1>
        <date></date> 
    </Node1> 
    <Node1> 
        <date></date> 
    </Node1> 
    <Node1> 
        <date></date> 
    </Node1> 
    <Node1> 
        <date></date> 
    </Node1> 
    <Node2> 
        <date></date> 
    </Node2> 
    <Node2> 
        <date></date> 
    </Node2> 
    <Node2> 
        <date></date> 
    </Node2> 
    <Node2> 
        <date></date> 
    </Node2> 
</root>

Я бы хотел отсортировать XML по дате (скажем, по порядку asc) независимо от того, находится ли дата под Node1 или Node2. На самом деле в коде Java у меня есть два отдельных списка, один с объектами Node1, а другой с объектами Node2. Я могу отсортировать список в произвольном порядке внутри Java. Но мне нужно отсортировать даты независимо от того, какие узлы работают в XML. Каков наилучший способ сортировки в Java?

На самом деле я использую Castor для сортировки java-объектов в XML. Если вы знаете, что это можно сделать с помощью Castor, это будет здорово!

Ответы [ 4 ]

2 голосов
/ 27 мая 2010

Я бы использовал XSLT, у него есть датчики с датами сортировки, которые вам нужно будет обойти, самый простой способ, если вы можете контролировать его, это иметь сортируемый формат даты, например, ггггммдд

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:template match="root">
    <xsl:copy>
        <xsl:apply-templates>
           <xsl:sort data-type="number" select="date"/>
        </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*">
      <xsl:copy>
          <xsl:apply-templates/>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>
1 голос
/ 27 мая 2010

Я также думаю, что сортировка XSL будет лучше и быстрее.

Проверьте следующие ссылки,

http://www.codeproject.com/KB/XML/sorting_dates_in_xsl.aspx

http://www.xml.com/pub/a/2002/07/03/transform.html?page=2

http://forums.devx.com/showthread.php?t=4063

спасибо.

0 голосов
/ 28 мая 2010

Я использовал XSLT и XALAN.

XSL, как показано ниже. Дата имеет формат мм / дд / гггг

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:template match="root"> 
<xsl:copy> 
<xsl:apply-templates> 
<xsl:sort data-type="number"  select="substring(date,7,4)"/> <!-- year sort -->
<xsl:sort data-type="number" select="substring(date,1,2)"/> <!-- day sort -->
<xsl:sort data-type="number" select="substring(date,4,2)"/> <!-- month sort -->
</xsl:apply-templates> 
</xsl:copy> 
</xsl:template> 
<xsl:template match="*"> 
<xsl:copy> 
<xsl:apply-templates/> 
</xsl:copy> 
</xsl:template> 
</xsl:stylesheet>

, а java-код

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

/**
 *  Use the TraX interface to perform a transformation in the simplest manner possible
 *  (3 statements).
 */
public class SimpleTransform
{
    public static void main(String[] args)
    throws TransformerException, TransformerConfigurationException, 
           FileNotFoundException, IOException
  {  
  // Use the static TransformerFactory.newInstance() method to instantiate 
  // a TransformerFactory. The javax.xml.transform.TransformerFactory 
  // system property setting determines the actual class to instantiate --
  // org.apache.xalan.transformer.TransformerImpl.
    TransformerFactory tFactory = TransformerFactory.newInstance();

    // Use the TransformerFactory to instantiate a Transformer that will work with  
    // the stylesheet you specify. This method call also processes the stylesheet
  // into a compiled Templates object.
    Transformer transformer = tFactory.newTransformer(new StreamSource("sort.xsl"));

    // Use the Transformer to apply the associated Templates object to an XML document
    // (foo.xml) and write the output to a file (foo.out).
    transformer.transform(new StreamSource("root.xml"), new StreamResult(new FileOutputStream("out.xml")));

    System.out.println("************* The result is in birds.out *************");
  }
}
0 голосов
/ 27 мая 2010

Если вы хотите, чтобы результат сортировки был одним списком, отсортированным по дате, вы должны поместить все узлы в один список массива. Если два типа (node1 и node2) расширяют общий базовый класс, вы можете использовать для вас список Generics в Java.

List<Node> nodes = new ArrayList<Node>();
nodes.add(node1);
nodes.add(node2);
Node[] nodeArrayToSort = nodes.toArray();

Если два типа узлов не наследуются от общего класса, вы можете просто использовать Список объектов.

Теперь вам нужно написать свой собственный компаратор. Вот пример, который вы можете использовать, если у типов узлов есть общий суперкласс, который содержит поле Date.

public class NodeComparator implements Comparator<Node> {
    @Override
    public int compare(Node node1, Node node2) {
        return node1.getDate().compare(node2.getDate());
    }
}

Теперь, когда у вас есть пользовательский компаратор и массив со всеми вашими узлами, это всего лишь одна строка кода Java для сортировки списка.

Arrays.sort(nodeArrayToSort, new NodeComparator());

Javadoc для вышеуказанного метода можно найти здесь , если вам нужна дополнительная информация о его поведении.

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

...