在 Java 中对 XML 进行排序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2917133/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 23:27:08  来源:igfitidea点击:

Sorting an XML in Java

javaxmlcastor

提问by Java Guy

I have an XML similar to below, which needs to be sorted using the date field.

我有一个类似于下面的 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>

I would like to sort the XML based on the date(say ascending order), irrespective of whether the date is under Node1 or Node2. Actually, in Java code I have two separate lists, one with Node1 objects and other with Node2 objects. I can sort the list in any order separately inside java. But I need to have the dates sorted irrespective of the nodes it is appearing on the XML. What is the best approach to sort this way in Java?

我想根据日期(比如升序)对 XML 进行排序,无论日期是在 Node1 还是 Node2 下。实际上,在 Java 代码中,我有两个单独的列表,一个包含 Node1 对象,另一个包含 Node2 对象。我可以在java中以任何顺序分别对列表进行排序。但是我需要对日期进行排序,而不管它出现在 XML 上的节点。在 Java 中以这种方式排序的最佳方法是什么?

Actually I am using Castor for marshaling the java objects to XML. If you know this can be done with Castor, that will be great!

实际上,我使用 Castor 将 java 对象编组为 XML。如果您知道这可以通过 Castor 完成,那就太好了!

采纳答案by blissapp

I'd use XSLT, it has probs with sorting dates that you'll need to work round, simplest way if you can control it is to have sortable date format like yyyymmdd

我会使用 XSLT,它有排序日期的问题,你需要处理,如果你能控制它,最简单的方法是使用可排序的日期格式,如 yyyymmdd

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

回答by Java Guy

I used XSLT and XALAN.

我使用了 XSLT 和 XALAN。

The XSL is as below.. Date is of the format mm/dd/yyyy

XSL 如下.. 日期格式为 mm/dd/yyyy

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

and the java code is

和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 *************");
  }
}

回答by Jesse Webb

If you would like the result of the sort to be a single list, sorted by date then you have to put all of the nodes into a single List of array. If the two types (node1 & node2) extend a common base class, you can use Java's Generics for you list.

如果您希望排序的结果是按日期排序的单个列表,那么您必须将所有节点放入一个数组列表中。如果这两种类型(node1 和 node2)扩展了一个公共基类,您可以使用 Java 的泛型为您列出。

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

If the two node types do not inherit from a common class, you can simply use a List of Objects.

如果这两种节点类型不从公共类继承,则可以简单地使用对象列表。

Now you will have to write your own Comparator. here is an example of one you could use if the node types do have a common super class which holds the Date field.

现在您必须编写自己的比较器。这是一个示例,如果节点类型确实有一个包含日期字段的公共超类,则您可以使用该示例。

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

Now that you have your custom comparator and your array with all of your nodes, it is a single line of Java code to sort the list.

现在您有了自定义比较器和包含所有节点的数组,只需一行 Java 代码即可对列表进行排序。

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

The javadoc for the above method can be found hereif you would like any additional info on it's behaviour.

如果您想了解有关其行为的任何其他信息,可以在此处找到上述方法的 javadoc 。

Using the above method, it is easy to see how you could write any type of compare function to change the behavior of your sort. You could also write as many custom Comparator classes as you'd please so that you could switch them at runtime. Hope this helps! :)

使用上述方法,很容易看出如何编写任何类型的比较函数来更改排序行为。您还可以根据需要编写任意数量的自定义 Comparator 类,以便您可以在运行时切换它们。希望这可以帮助!:)