[英]Take a DOM and re-order nodes and attributes in alphabetical order
我想閱讀 XML 文檔,以確定的順序重新排序節點和屬性,例如:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com</groupId>
<artifactId>foobar</artifactId>
<version>0.0.1-SNAPSHOT</version>
</project>
變成:
<project>
<artifactId>foobar</artifactId>
<groupId>com</groupId>
<modelVersion>4.0.0</modelVersion>
<version>0.0.1-SNAPSHOT</version>
</project>
我也想做屬性和縮進!
您的示例沒有任何屬性,通常您無法控制屬性的順序。 但是在 XSLT 中對元素進行排序很容易:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates>
<xsl:sort select="name()"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
您可以使用 XSLT 轉換 XML 數據並使用<xsl:sort>
對元素進行排序
我可以推薦 JDOM2 來完成這種工作。 您的建議可以這樣實現:
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.filter.Filters;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.jdom2.xpath.XPathExpression;
import org.jdom2.xpath.XPathFactory;
public void transformXmlFile(File oldFile, File newFile) throws Exception
{
Document oldDocument = new SAXBuilder().build(oldFile);
Document newDocument = new Document(transformElement(oldDocument.getRootElement()));
List<Element> children = new LinkedList<Element>();
for (Element oldElement : oldDocument.getRootElement().getChildren())
children.add(transformElement(oldElement));
for (Element oldElement : sortElements(children))
newDocument.getRootElement().addContent(oldElement);
XMLOutputter serializer = new XMLOutputter(Format.getPrettyFormat());
serializer.output(newDocument, new FileOutputStream(newFile));
}
private Element transformElement(Element oldElement)
{
Element newElement = new Element(oldElement.getName(), oldElement.getNamespace());
List<Attribute> attributes = new LinkedList<Attribute>();
for (Attribute a: oldElement.getAttributes())
attributes.add(a.clone());
for (Attribute a: sortAttributes(attributes))
newElement.getAttributes().add(a);
return newElement;
}
private List<Attribute> sortAttributes(List<Attribute> attributes)
{
Collections.sort(attributes, new Comparator<Attribute>()
{
@Override
public int compare(Attribute a1, Attribute a2)
{
return a1.getName().compareTo(a2.getName());
}
});
return attributes;
}
private List<Element> sortElements(List<Element> elements)
{
Collections.sort(elements, new Comparator<Element>()
{
@Override
public int compare(Element e1, Element e2)
{
return e1.getName().compareTo(e2.getName());
}
});
return elements;
}
這確實是 mkdev 的答案,但經過調整以對整個文件進行排序,而不僅僅是頂級節點。
import java.io.File;
import java.io.FileOutputStream;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import org.jdom2.Attribute;
import org.jdom2.Content;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
//Source: https://stackoverflow.com/a/17502935/1361991
public class XMLSorter2 {
public void transformXmlFile(File oldFile, File newFile) throws Exception
{
Document oldDocument = new SAXBuilder().build(oldFile);
Document newDocument = new Document((Element) transformElement(oldDocument.getRootElement()));
List<Content> children = new LinkedList<Content>();
for (Content oldElement : oldDocument.getRootElement().getContent())
children.add(transformElement(oldElement));
for (Content oldElement : sortElements(children))
newDocument.getRootElement().addContent(oldElement);
XMLOutputter serializer = new XMLOutputter(Format.getPrettyFormat());
serializer.output(newDocument, new FileOutputStream(newFile));
}
private Content transformElement(Content oldContent)
{
if(!(oldContent instanceof Element))
return oldContent.clone();
Element oldElement = (Element)oldContent;
Element newElement = new Element(oldElement.getName(), oldElement.getNamespace());
List<Attribute> attributes = new LinkedList<Attribute>();
for (Attribute a: oldElement.getAttributes())
attributes.add(a.clone());
for (Attribute a: sortAttributes(attributes))
newElement.getAttributes().add(a);
List<Content> children = new LinkedList<Content>();
for (Content oldElementChildren : oldElement.getContent())
children.add(transformElement(oldElementChildren));
for (Content oldElementChildren : sortElements(children))
newElement.addContent(oldElementChildren);
return newElement;
}
private List<Attribute> sortAttributes(List<Attribute> attributes)
{
Collections.sort(attributes, new Comparator<Attribute>()
{
public int compare(Attribute a1, Attribute a2)
{
return a1.getName().compareTo(a2.getName());
}
});
return attributes;
}
private List<Content> sortElements(List<Content> elements)
{
Collections.sort(elements, new Comparator<Content>()
{
public int compare(Content e1, Content e2)
{
if(e1 instanceof Element && e2 instanceof Element)
return ((Element)e1).getName().compareTo(((Element)e2).getName());
else if(e1 instanceof Element)
return -1;
else if(e2 instanceof Element)
return 1;
else
return e1.getValue().compareTo(e2.getValue());
}
});
return elements;
}
public static void main(String[] args) {
try {
new XMLSorter2().transformXmlFile(new File(args[0]), new File(args[1]));
} catch (Exception e) {
e.printStackTrace();
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.