Home > Blockchain >  sort xml elements based on their child node getTextContent value
sort xml elements based on their child node getTextContent value

Time:01-06

I have been trying to reorder xml elements based on their child getTextContent value, but everything that I tried only worked for siblings nodes

Basically, I have this XML:

<order>
    <item>
        <item-id>d54829d52c3f2810VgnVCM1000001af614ac</item-id>
        <item-order>3</item-order>
    </item>
    <item>
        <item-id>b54829d52c3f2810VgnVCM1000001af614ac</item-id>
        <item-order>1</item-order>
    </item>
    <item>
        <item-id>f54829d52c3f2810VgnVCM1000001af614ac</item-id>
        <item-order>2</item-order>
    </item>
</order>

And I would like to achive this result, ordering using "item-order":

<order>
    <item>
        <item-id>b54829d52c3f2810VgnVCM1000001af614ac</item-id>
        <item-order>1</item-order>
    </item>
    <item>
        <item-id>f54829d52c3f2810VgnVCM1000001af614ac</item-id>
        <item-order>2</item-order>
    </item>
    <item>
        <item-id>d54829d52c3f2810VgnVCM1000001af614ac</item-id>
        <item-order>3</item-order>
    </item>
</order>

I have been trying some implementations like this example based on the website below that I found on internet, but it does not work.

http://programmatica.blogspot.com/2006/12/sorting-xml-in-java.html How to sort XML elements by value of attributes in Java?

static class MyComparator4 implements Comparator {

        public int compare(Object arg0, Object arg1) {
    
            if (arg0 instanceof Element && arg1 instanceof Element) {
    
                Element e0 = (Element) arg0;
                Element e1 = (Element) arg0;

e0.getChildNodes().item(e0.getChildNodes().getLength()-1).getTextContent().compareTo(e1.getChildNodes().item(e1.getChildNodes().getLength()-1).getTextContent());

            } else {
                return ((Node) arg0).getNodeName().compareTo(
                        ((Node) arg1).getNodeName());
            }
    
        }
    
    }

Any help is appreciate. Thank you in advance

CodePudding user response:

You can use the class (public class NodeTools) from your 2nd example (link) with the Integer class which is comparable.

Node[] ret = NodeTools.sortNodes(doc.getElementsByTagName("item"), "item-order", true, Integer.class);

CodePudding user response:

Based on what @mazi suggested, I was able to achieve the ordering changing a little bit the method NodeTools.sortNodes.

Basically, I have changed this part:

            bda = (Comparable)bc.newInstance(((Element)a).getAttribute(attributeName));
            bdb = (Comparable)bc.newInstance(((Element)b).getAttribute(attributeName));

To this:

            bda = (Comparable)bc.newInstance(((Element)a).getElementsByTagName(attributeName).item(0).getTextContent());
            bdb = (Comparable)bc.newInstance(((Element)b).getElementsByTagName(attributeName).item(0).getTextContent());

Here goes the whole code:



    import java.lang.reflect.Constructor;
    import java.util.*;
    
    import org.w3c.dom.Element;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    
    import org.xml.sax.InputSource;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import java.io.StringReader;
    import org.w3c.dom.Document;
    
    public class NodeTools {
    
        public static Node[] sortNodes(NodeList nl, String attributeName, boolean asc, Class B)
        {
            class NodeComparator implements Comparator
            {
                @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).getElementsByTagName(attributeName).item(0).getTextContent());
                        bdb = (Comparable)bc.newInstance(((Element)b).getElementsByTagName(attributeName).item(0).getTextContent());
                        //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 x = new ArrayList();
            for(int i = 0; i ());
            return ret;
        }
    
        public static void main(String... args)
        {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder;
            String s = "\n"  
                    "    \n"  
                    "        d54829d52c3f2810VgnVCM1000001af614ac\n"  
                    "        3\n"  
                    "    \n"  
                    "    \n"  
                    "        b54829d52c3f2810VgnVCM1000001af614ac\n"  
                    "        1\n"  
                    "    \n"  
                    "    \n"  
                    "        f54829d52c3f2810VgnVCM1000001af614ac\n"  
                    "        2\n"  
                    "    \n"  
                    "";
    
            Document doc = null;
            try
            {
                builder = factory.newDocumentBuilder();
                doc = builder.parse(new InputSource(new StringReader(s)));
            }
            catch(Exception e) { System.out.println("Alarm " e); return; }
    
            Node[] ret = NodeTools.sortNodes(doc.getElementsByTagName("item"), "item-order", true, Integer.class);
            for(Node n: ret)
            {
                System.out.println(((Element)n).getTextContent());
            }
        }
    }

Here is the output:

    b54829d52c3f2810VgnVCM1000001af614ac
    1


    f54829d52c3f2810VgnVCM1000001af614ac
    2


    d54829d52c3f2810VgnVCM1000001af614ac
    3
  • Related