18

I have following scenario: I have a XML-Document, e.g. like this

<someRootElement>
<tag1>
    <tag2 
        someKey=someValue
        someKey2=someValue2
    />
    <tag3/>
    <tag4
        newKey=newValue
        newKey2=newValue2
    />
</tag1>
</someRootElement>

Now I want the parent tag1 to be called reallyCoolTag without losing the childnodes. I tried the following, but it unfortunately doesn't work as I wish it would (but I do know why, b/c it is missing something, I guess):

// the new element:
Element neu = doc.createElement( newValue );
// append it to the root:
root.appendChild( neu );
// get all the child nodes:
NamedNodeMap nnm = nodes.item(i).getAttributes();
for( int dg = 0; dg < nnm.getLength(); dg++ ){
    neu.setAttribute(  nnm.item( dg ).getNodeName(),
    nnm.item( dg ).getNodeValue() );
}
//---------------------------------------------------------
// HERE I GUESS I AM MISSING THE PART WHERE THE CHILD NODES
// ARE BEING APPENDED TO THE NEW NODE?????
//---------------------------------------------------------
// nodes.item(i) := the old value (nodes := is a NodeList
root.replaceChild( neu, nodes.item(i));
TransformerFactory tFactory     = TransformerFactory.newInstance();
Transformer transformer         = tFactory.newTransformer();
DOMSource source                = new DOMSource( doc );
StreamResult result         = new StreamResult( xml );
transformer.transform( source, result );
nodes.item( i ).getParentNode().removeChild( nodes.item(i) );

Now this does work to a certain extend, as I mentioned, I guess I am missing the part where the child nodes are being appened, but what I actually wanted to know is, whether there is a really short way to rename the parent node without having to copy everything and replace the whole thing?

Thnx in advance!!!

5 Answers 5

39

Using Document.renameNode:

NodeList nodes = document.getElementsByTagName("tag1");
for (Node eachNode: nodes) {
  document.renameNode(eachNode, null, "reallyCoolTag");
}
Sign up to request clarification or add additional context in comments.

Comments

2

You could use an XSL Transformation (XSLT) for this:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">
  <xsl:output method="xml" indent="yes" />
  <xsl:template match="*"> <!-- match anything -->
    <xsl:copy>
      <xsl:copy-of select="@*" />
      <xsl:apply-templates />
    </xsl:copy>
  </xsl:template>
  <xsl:template match="tag1"> <!-- switch the element name -->
    <xsl:element name="reallyCoolTag">
      <xsl:copy-of select="@*" />
      <xsl:apply-templates />
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

This can be used with the javax.xml.transform package (Java 1.4 and above):

TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer(new StreamSource(
    new File("RenameTag.xslt")));
transformer
    .transform(new DOMSource(document), new StreamResult(System.out));

See DOMResult if you want a Document as the output.

1 Comment

If you also need to run java code to run the style sheet, it may be better to use only java to solve the problem. In doing so, you limit the technologies involved, disk access and disk dependencies. You may prefer style sheets when there are several changes to make and they are more heterogeneous. I Suggest Using Document.renameNode
0

Your tag1 is invalid. It doesn't have closing >. Also the attributes should be quoted. It should look like this,

<someRootElement>
<tag1>
    <tag2 
        someKey="someValue"
        someKey2="someValue2"
    />
    <tag3/>
    <tag4
        newKey="newValue"
        newKey2="newValue2"
    />
</tag1>
</someRootElement>

Try with the corrected XML. It should work.

1 Comment

aside from that the suggested methods did not work ... I had to loop through the children of the node and add em ... but you are right, it isn't valid the way I put it.
0

Just call setName("reallyCoolTag") on the element(s) you want to rename. There is no need to copy the children around; the name attribute of an element is a mutable field.

4 Comments

I've tried that before, but it didn't work. Maybe I am doing it wrong? If the node I want to rename is 'nodes.item(i)' and the root-element is called root, how exactly am I doing that? I've tried: nodes.item(i).setName(newValue) ... but eclipse wants me to add a cast ...
It does work; it just doesn't change the file on disk. You need to save the document in RAM somewhere to see the effect.
see above, eclipse wants me to add a cast ... I guess, the method is not supposed to work that way ... and as you can see above I am saving the changes I want to make :(
Sorry, I didn't mean the root element but the element(s) you want renamed. There is really no need to copy the children. Just search for the elements you want renamed and call setName() on them.
0

As you did get the attributes:

NamedNodeMap nnm = nodes.item(i).getAttributes();

and you added these attributes to the new element,

You should get the children of nodes.item(i) and set them in the new node.

You can use for ex.:

neu.addContent(nodes.item(i).getChildren());

2 Comments

Maybe I should get a new eclipse or it really doesn't know 'addContent' :(
sorry, I was using JDOM. By org.w3c: you can use nodes.item(i).getChildNodes(); //return list of child then loop on them using appendChild(Element); //to append each child

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.