How to reorder a node using XML Java DOM

Here is what I have

<animation_state> <state>run</state> <animation_sequence> <pose duration="10" image_id="1"/> <pose duration="10" image_id="2"/> <pose duration="10" image_id="3"/> </animation_sequence> 

I would like to give the user the ability to move a specific image up and down, however, since they are stored in XML, this means that I need to change the identifiers of the images around. Assuming the user wants image_id = 3 to be first in the sequence or in the middle, or anywhere depending on his needs, how can I manipulate XML? I am using the DOM.

If the user wants image 3 to be the first, my XML should look like this:

 <animation_state> <state>run</state> <animation_sequence> <pose duration="10" image_id="3"/> <pose duration="10" image_id="1"/> <pose duration="10" image_id="2"/> </animation_sequence> 

My attempt:

 Document dom = parser.getDocument(); for (int i = 0; i < dom.getElementsByTagName("animation_state").getLength(); i++) { if (dom.getElementsByTagName("animation_state").item(i).getChildNodes().item(0).getTextContent().equalsIgnoreCase(target)) { posVal = i; } } NodeList list = dom.getElementsByTagName("animation_sequence").item(posVal).getChildNodes(); for(int b=0; b<list.getLength(); b++) { if(list.item(b).getAttributes().item(1).getNodeValue().equalsIgnoreCase(PoseSelectionListener.imageIDOfSelectedPose)) { Node toBeMoved = list.item(b); dom.getElementsByTagName("animation_sequence").item(posVal).appendChild(toBeMoved); System.out.println(toBeMoved.getAttributes().item(0).getNodeName()); } } 
+4
source share
2 answers

Use Node.insertBefore and / or Node.appendChild Just find the Node to move and find the place where it should be moved, and insert this Node in front of it.

It may be easier for you to create a copy of Node to move, paste it in the right place, and delete the old node .

See the sample code below:

 public class SO13782330 { /** Move the image whose imageId is given at first position in sequence */ public static void moveImageFirst(Document doc, int imageId) throws Exception { XPath xpath = XPathFactory.newInstance().newXPath(); // get the image to move XPathExpression poseXPath = xpath.compile("//pose[@image_id='" + imageId + "']"); Node pose = (Node)poseXPath.evaluate(doc, XPathConstants.NODE); // get the first image XPathExpression firstPoseXPath = xpath.compile("//pose[position() = 1]"); Node firstPose = (Node)firstPoseXPath.evaluate(doc, XPathConstants.NODE); // copy the image to be moved Node poseCopy = pose.cloneNode(true); // insert it before the first one Node sequence = firstPose.getParentNode(); sequence.insertBefore(poseCopy, firstPose); // delete the old one sequence.removeChild(pose); } /** Print the document on stdout */ public static void showDocument(Document doc) throws Exception { Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); StringWriter sw = new StringWriter(); transformer.transform(new DOMSource(doc), new StreamResult(sw)); System.out.println(sw.getBuffer().toString()); } public static void main(String... args) throws Exception { DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document doc = db.parse(new InputSource(new StringReader("<animation_state>\n" + "<state>run</state>\n" + "<animation_sequence>\n" + "<pose duration=\"10\" image_id=\"1\"/>\n" + "<pose duration=\"10\" image_id=\"2\"/>\n" + "<pose duration=\"10\" image_id=\"3\"/>\n" + "</animation_sequence>\n" + "</animation_state>"))); moveImageFirst(doc, 3); showDocument(doc); } } 

It moves the pose element that has the image_id attribute equal to 3 before the first.

+4
source

You do not need to copy / clone node.

Just follow these steps:

 public void addNodeAfter(Node newNode, Node refChild) { Node parent = refChild.getParent(); parent.insertBefore(newNode, refChild); refChild = parent.remove(refChild); parent.insertBefore(refChild, newNode); } 

May be a better solution than cloning.

+3
source

All Articles