views:

1346

answers:

5

Hey,

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!!!

+1  A: 

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.

Aaron Digulla
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 ...
doro
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.
Aaron Digulla
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 :(
doro
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.
Aaron Digulla
A: 

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());

Moro
Maybe I should get a new eclipse or it really doesn't know 'addContent' :(
doro
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
Moro
A: 

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.

ZZ Coder
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.
doro
A: 

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.

McDowell
+2  A: 

Using Document.renameNode:

NodeList nodes = document.getElementsByTagName("tag1");
for (int i = 0; i < nodes.getLength(); i++) {
  document.renameNode(nodes.item(i), null, "reallyCoolTag");
}
McDowell
i'll try that, thnx :)
doro