如何使用Java在XML文件中重新排列子元素

时间:2013-05-01 13:51:04

标签: java xml parsing dom xml-parsing

我有一个xml文件,我希望根据某些属性重新定位子元素(如下例中的“id”值)。 我希望以“bk103”将成为第一个孩子的方式重写xml文件。 我的问题不是关于如何对子元素进行排序(可以使用“if”条件)。我想知道是否有办法解析xml文件并按照我希望它的顺序重写xml文件中的元素(比如书ID的升序)

我应该使用什么方法来做这件事,如果有人可以提出算法来做同样的事情。

<?xml version="1.0"?>
<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>enter code here
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications 
      with XML.</description>
   </book>
   <book id="bk102">
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-12-16</publish_date>
      <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.</description>
   </book>
   <book id="bk103">
      <author>Corets, Eva</author>
      <title>Maeve Ascendant</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-11-17</publish_date>
      <description>After the collapse of a nanotechnology 
      society in England, the young survivors lay the 
      foundation for a new society.</description>
   </book>
</catalog>


Output:

<?xml version="1.0"?>
<catalog>
    <book id="bk103">
      <author>Corets, Eva</author>
      <title>Maeve Ascendant</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-11-17</publish_date>
      <description>After the collapse of a nanotechnology 
      society in England, the young survivors lay the 
      foundation for a new society.</description>
   </book>
<book id="bk102">
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-12-16</publish_date>
      <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.</description>
   </book>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications 
      with XML.</description>
   </book>


</catalog>

4 个答案:

答案 0 :(得分:1)

您可以使用XQuery重新排列XML中的<book/>节点。

declare variable $input-document external;

<catalog>
{
  for $book in doc($input-document)/catalog/book
  let $id := $book/data(@id)
  order by $id descending
  return $book
}
</catalog>

使用像Saxon这样的XQuery引擎,您可以从命令行转换XML:

java -cp saxon9he.jar net.sf.saxon.Query input-document=input.xml reorder.xq 

saxon9he.jar是Saxon HE JAR,XQuery变量$input-document绑定到'input.xml'调用文件reorder.xq中的XQuery。

如果您确实需要从Java调用XQuery,可以使用XQJ来完成。

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.xml.namespace.QName;
import javax.xml.xquery.XQConnection;
import javax.xml.xquery.XQDataSource;
import javax.xml.xquery.XQException;
import javax.xml.xquery.XQPreparedExpression;
import javax.xml.xquery.XQSequence;

import net.sf.saxon.xqj.SaxonXQDataSource;


public class ReorderXml {

  public static void main(String[] args) throws XQException, IOException {

    // Use XQJ to execute an XQuery with Saxon HE
    XQDataSource ds = new SaxonXQDataSource();
    XQConnection conn = ds.getConnection();

    // InputStream for the XQuery
    InputStream query = new FileInputStream("reorder.xq");

    // Create a prepared expression ...
    XQPreparedExpression exp = conn.prepareExpression(query);

    // ... and bind the path to the input document to XQuery variable $input-document
    exp.bindString(new QName("input-document"), "data/input.xml", null);

    // Execute the query and ...
    XQSequence xqs = exp.executeQuery();

    // ... print the resulting document to standard out.
    xqs.writeSequence(System.out, null);

    // Clean up (production code should do that in a finally clause!)
    xqs.close();
    conn.close();
    query.close();
  }

}

还有一些其他XQuery引擎,如ZorbaMXQuery

答案 1 :(得分:0)

你需要一个优秀的java xml解析器。然后,您可以使用它来创建一个具有您选择的安排的新xml文档。实际上MKYong已经在java中涵盖了Reading from an xml documentcreating an xml document。他还介绍了检索元素属性中的值。

答案 2 :(得分:0)

以下示例读取源文件“xmlFile.xml”,按字母顺序对书籍节点进行反向排序,并将结果写入新文件“newXmlFile.xml”。

package org.example;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

public class XmlElementOrder {

    private static final String ID = "id";
    private static final String PATH_PREFIX = "src/main/resources/";
    private static final String SOURCE_FILE = "xmlFile.xml";
    private static final String TARGET_FILE = "newXmlFile.xml";

    public static void main(String[] args) throws JDOMException, IOException {

        File xmlFile = new File(PATH_PREFIX + SOURCE_FILE);
        SAXBuilder builder = new SAXBuilder();
        Document document = builder.build(xmlFile);

        Element rootElement = document.detachRootElement();
        List<Element> children = new ArrayList<Element>(rootElement.getChildren());
        rootElement.removeContent();

        Comparator<Element> comparator = new Comparator<Element>() {
            public int compare(Element o1, Element o2) {
                return o2.getAttributeValue(ID).compareTo(o1.getAttributeValue(ID));
            }
        };
        Collections.sort(children, comparator);

        Document newDocument = new Document(rootElement);
        rootElement.addContent(children);

        XMLOutputter xmlOutput = new XMLOutputter();
        xmlOutput.setFormat(Format.getPrettyFormat());
        xmlOutput.output(newDocument, new FileWriter(PATH_PREFIX + TARGET_FILE));

    }
}

该示例使用JDOM库。如果您使用的是Maven,可以按照以下方式将其包含在POM中:

<dependency>
    <groupId>org.jdom</groupId>
    <artifactId>jdom</artifactId>
    <version>2.0.2</version>
</dependency>

答案 3 :(得分:0)

只需更改比较器:

        Comparator<Element> comparator = (op1,op2) -> op2.getChildText(ID).compareTo(op1.getChildText(ID));    

西蒙