我有一个XML字符串,我需要按属性对其进行排序。这是输入XML字符串:
<graph>
<root root_id="1"/>
<type name="A">
<extends name="Sphere"/>
</type>
<node id="3" name="" type="A">
<property name="radius" value="0.1"/>
</node>
<edge id="2" src_id="5" dest_id="3" type="successor"/>
<node id="4" name="" type="L">
<property name="length" value="3.0"/>
</node>
<edge id="3" src_id="1" dest_id="4" type="successor"/>
<node id="5" name="" type="P">
<property name="color" value="14"/>
</node>
<edge id="4" src_id="4" dest_id="5" type="successor"/>
</graph>
这是期待的结果:
<graph>
<root root_id="1"/>
<type name="A">
<extends name="Sphere"/>
</type>
<edge id="3" src_id="1" dest_id="4" type="successor"/>
<node id="4" name="" type="L">
<property name="length" value="3.0"/>
</node>
<edge id="4" src_id="4" dest_id="5" type="successor"/>
<node id="5" name="" type="P">
<property name="color" value="14"/>
</node>
<edge id="2" src_id="5" dest_id="3" type="successor"/>
<node id="3" name="" type="A">
<property name="radius" value="0.1"/>
</node>
</graph>
基本上,在edge的属性src_id和dest_id的帮助下,节点必须一个接一个地与边连接。任何想法将非常感谢!非常感谢你!
答案 0 :(得分:1)
对于数据类型(String,Integer,Double等),此Class按属性的值对NodeList进行排序。
以下是完整的解决方案:
package mynewpackage;
// for the method
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
// for the test example
import org.xml.sax.InputSource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;
import org.w3c.dom.Document;
import java.math.BigDecimal;
public class NodeTools {
/**
* Method sorts any NodeList by provided attribute.
* @param nl NodeList to sort
* @param attributeName attribute name to use
* @param asc true - ascending, false - descending
* @param B class must implement Comparable and have Constructor(String) - e.g. Integer.class , BigDecimal.class etc
* @return Array of Nodes in required order
*/
public static Node[] sortNodes(NodeList nl, String attributeName, boolean asc, Class<? extends Comparable> B)
{
class NodeComparator<T> implements Comparator<T>
{
@Override
public int compare(T a, T b)
{
int ret;
Comparable bda = null, bdb = null;
try{
Constructor bc = B.getDeclaredConstructor(String.class);
bda = (Comparable)bc.newInstance(((Element)a).getAttribute(attributeName));
bdb = (Comparable)bc.newInstance(((Element)b).getAttribute(attributeName));
}
catch(Exception e)
{
return 0; // yes, ugly, i know :)
}
ret = bda.compareTo(bdb);
return asc ? ret : -ret;
}
}
List<Node> x = new ArrayList<>();
for(int i = 0; i < nl.getLength(); i++)
{
x.add(nl.item(i));
}
Node[] ret = new Node[x.size()];
ret = x.toArray(ret);
Arrays.sort(ret, new NodeComparator<Node>());
return ret;
}
// Test with simple example
public static void main(String... args)
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
String s = "<xml><item id=\"1\" price=\"100.00\" /><item id=\"3\" price=\"29.99\" /><item id=\"2\" price=\"5.10\" /></xml>";
Document doc = null;
try
{
builder = factory.newDocumentBuilder();
doc = builder.parse(new InputSource(new StringReader(s)));
}
catch(Exception e) { System.out.println("Alarm "+e); return; }
System.out.println("*** Sort by id ***");
Node[] ret = NodeTools.sortNodes(doc.getElementsByTagName("item"), "id", true, Integer.class);
for(Node n: ret)
{
System.out.println(((Element)n).getAttribute("id")+" : "+((Element)n).getAttribute("price"));
}
System.out.println("*** Sort by price ***");
ret = NodeTools.sortNodes(doc.getElementsByTagName("item"), "price", true, BigDecimal.class);
for(Node n: ret)
{
System.out.println(((Element)n).getAttribute("id")+" : "+((Element)n).getAttribute("price"));
}
}
}
在我的简单测试中,它打印出来:
*** Sort by id ***
1 : 100.00
2 : 5.10
3 : 29.99
*** Sort by price ***
2 : 5.10
3 : 29.99
1 : 100.00