Sam
Sam

Reputation: 51

JAXB Tree Structure formatting with references to its Parent not working

I need to bring the data from database table and need to display it in the below XML tree format.

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <ROOT>
        <Rows>
            <Row id =1 name=" " desc="" parentId="0">
               <Row id = 2 name="" desc="" parentId="1" >
                    <Row id = 3 name="" desc="" parentId="2" />
            </Row>
            <Row id = 4 name=" " desc="" parentId="0" />
        </Rows>
    </ROOT>

Java Class

@XmlRootElement(namespace = "com.abc.ROOT")
@XmlAccessorType(XmlAccessType.FIELD)

public class Rows implements Serializable {

    private static final long serialVersionUID = 1;

    @XmlAttribute
    private int id;

    @XmlAttribute
    private String name;

    @XmlAttribute
    private String description;

    @XmlAttribute
    private int levelNumber;

    @XmlAttribute
    private Integer parentNodeId;

    //If I have the following code, then rather than pulling the single id, it creates one more tree inside and displays all hierarchical structure for its parent node
    //@XmlAttribute
    //private Rows parentNodeId
    }

With the above code I get the plain formatting with random ordering as

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ROOT>
    <Rows>
        <Row id = 3 name="" desc="" parentId="2" />
        <Row id = 1 name=" " desc="" parentId="0"/>
        <Row id = 4 name=" " desc="" parentId="0" />
        <Row id = 2 name="" desc="" parentId="1"/>
    </Rows>
</ROOT>

How do I get the tree stcuture in XML with proper ordering like nested tree stucture? I need to display the nested tree structure.

UPDATE : 12/10/2014.

When I Modified my Row class with the following changes, I'm getting tree structure in revserse order. i.e from child to parent. So I'm getting multiple rows printed for each child pointing all the way back to parent

Java Class

@XmlRootElement(namespace = "com.abc.ROOT") @XmlAccessorType(XmlAccessType.FIELD)

public class Rows implements Serializable {

private static final long serialVersionUID = 1;

@XmlAttribute
private int id;

@XmlAttribute
private String name;

@XmlAttribute
private String description;

@XmlAttribute
private int levelNumber;

**@XmlElement**
private **Rows** parentNodeId;

//If I have the following code, then rather than pulling the single id, it creates one more tree inside and displays all hierarchical structure for its parent node
//@XmlAttribute
//private Rows parentNodeId
}

In Hibernate file, I've defined the many to one relationship with PARENT_ID being the foreign key.

I'm getting

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <ROOT>
        <Rows>
            <Row id = 3 name="" desc="" parentId="2" >
               <Row id = 2 name="" desc="" parentId="1">
                   <Row id = 1 name=" " desc="" parentId="0"/>
               </Row>
            <Row>
            <Row id = 4 name="" desc="" parentId="1" >
                   <Row id = 1 name=" " desc="" parentId="0"/>
               </Row>
        </Rows>
    </ROOT>

How do I get this sorted with Parent first?

@lounce - I'm getting data from my JPA class in the above order. So how shall I determine and add the child row?

Upvotes: 0

Views: 676

Answers (1)

laune
laune

Reputation: 31290

Your class Rows doesn't represent a tree structure, and therefore you don't get a tree. The following couple of classes will marshal closer to what you need, but it's not complete.

@XmlRootElement
public class Tree {
    @XmlElement( name = "Row" )
    private List<Node> node;
    public Tree(){}
    public List<Node> getNode(){ 
        if( node == null ) node = new ArrayList<>();
        return node; 
    }
}

public class Node {
    private int id;
    @XmlElement(name="Row")
    private List<Node> node;
    public Node( int id ){
        this.id = id;
    }
    @XmlAttribute
    public int getId(){ return id; }
    public void setId( int value ){ id = value; }
    public List<Node> getNode(){ 
    if( node == null ) node = new ArrayList<>();
        return node; 
    }
}

To marshal:

    Tree tree = new Tree();
    Node n1 = new Node(1);
    tree.getNode().add( n1 );
    Node n2 = new Node(2);
    n1.getNode().add( n2 );
    Node n3 = new Node(3);
    n2.getNode().add( n3 );
    Node n4 = new Node(4);
    tree.getNode().add( n4 );
    JAXBContext jc = JAXBContext.newInstance( Tree.class );
    Marshaller m = jc.createMarshaller();
    m.marshal( tree, ... );

It is, of course, up to you to interpret the id and parent data in your row elements so that the tree is arranged correctly - neither JAXB not I will do this for you ;-)

This is what I get:

<tree>
    <Row id="1">
        <Row id="2">
            <Row id="3"/>
        </Row>
    </Row>
    <Row id="4"/>
</tree>

Later

To get the correct linkage according to parentId, you can store all Node objects in an array according to their id-1; let's call this array nodesById. Then:

for( Node node: nodesById ){
    int pid = node.getParentId();
    if (pid == 0){
       tree.getNode().add( node );
    } else {
       nodesById[pid-1].getNode().add( node );
    }
}

Upvotes: 3

Related Questions