• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 238
  • Last Modified:

Change parent element name to child text node value

Hi,

I have an XML document I am traversing using the Document Object Model (DOM).  The code needs to process any number of different xml formats so I will never know what the incoming XML document looks like.  I have a path to an element which I need to use it's text node value to replace it's parent element name.  I can get a reference to the child element, and it's text node value using it's path and to the parent using the getParent() function.  I cannot however figure out how to change the name of the parent element.  Also, once I change the parent element name, I need to remove the child from the parent.

Here is an example document:
<TRANSACTION>
    <HEADER>
        <BusinessPartnerID>ABCDDD</BusinessPartnerID>
        <SentDate>2005-04-15</SentDate>
        <SentTime>03:08:30</SentTime>
        <TransactionCount>2</TransactionCount>
    </HEADER>
    <EVENT>
        <Account>F04000178</Account>
        <EVENT_TYPE>PROBATE</EVENT_TYPE>
        <Date>15-Apr-2005 00:00:00</Date>
    </EVENT>
    <EVENT>
        <Account>F04000178</Account>
        <EVENT_TYPE>AUDIT</EVENT_TYPE>
        <Date>15-Apr-2005 00:00:00</Date>
    </EVENT>
</TRANSACTION>

I have the following path: /TRANSACTION/EVENT/EVENT_TYPE

I need my resulting document to look like this:
TRANSACTION>
    <HEADER>
        <BusinessPartnerID>ABCDDD</BusinessPartnerID>
        <SentDate>2005-04-15</SentDate>
        <SentTime>03:08:30</SentTime>
        <TransactionCount>2</TransactionCount>
    </HEADER>
    <PROBATE>
        <Account>F04000178</Account>
        <Date>15-Apr-2005 00:00:00</Date>
    </PROBATE>
    <AUDIT>
        <Account>F04000178</Account>
        <Date>15-Apr-2005 00:00:00</Date>
    </AUDIT>
</TRANSACTION>

I realize I could use XSL to transform the document, however, since I have no idea what the incoming document looks like (only the path of the element to use to modify it's parent name), I would have to generate the XSL dynamically, which I'm thinking would be even more difficult.

Thanks


0
trudyhlittle
Asked:
trudyhlittle
  • 4
  • 2
1 Solution
 
aozarovCommented:
>>I cannot however figure out how to change the name of the parent element.
I don't think you can. just create a new element  vi doc.createElement("new_element_name");
add the children of the old element to the new element via getChildNodes() and appendChild (inside iteration)
and remove the old element via removeChild(element);
0
 
aozarovCommented:
For examples look at: http://javaalmanac.com/cgi-bin/search/find.pl?words=DOM
In your case you only care about two classes Document (to create new element) and Node.
http://java.sun.com/j2se/1.4.2/docs/api/org/w3c/dom/Node.html
0
 
trudyhlittleAuthor Commented:
Thanks, I've got the new element added and all the children moved to the new parent.  I am now having difficulty removing the old elements.  I am using one of the examples you provided a link to, but only one of my elements is being removed.  I am using the removeAll method:

 public static void removeAll(Node node, short nodeType, String name) {
    if (node.getNodeType() == nodeType &&
        (name == null || node.getNodeName().equals(name))) {
      node.getParentNode().removeChild(node);
    }
    else {
      // Visit the children
      NodeList list = node.getChildNodes();
      for (int i = 0; i < list.getLength(); i++) {
        removeAll(list.item(i), nodeType, name);
      }
    }
  }

I am calling: removeAll(pXML, Node.ELEMENT_NODE, vParentNodeName) where pXML is the document bellow, and vParentNodeName is "EVENT".

<TRANSACTION>
    <HEADER>
        <BusinessPartnerID>ECEVARR</BusinessPartnerID>
        <SentDate>2005-04-18</SentDate>
        <SentTime>11:38:01</SentTime>
        <TransactionCount>3</TransactionCount>
    </HEADER>
    <EVENT>
        <EVENT_TYPE>PROBATE</EVENT_TYPE>
    </EVENT>
    <EVENT>
        <EVENT_TYPE>AUD</EVENT_TYPE>
    </EVENT>
    <PROBATE>
        <Account>F04000178</Account>
        <Date>2005-04-18</Date>
    </PROBATE>
    <AUD>
        <Account>F04000178</Account>
        <Date>2005-04-18</Date>
    </AUD>
</TRANSACTION>

After I call the function my XML looks like this:

<TRANSACTION>
    <HEADER>
        <BusinessPartnerID>ECEVARR</BusinessPartnerID>
        <SentDate>2005-04-18</SentDate>
        <SentTime>11:38:01</SentTime>
        <TransactionCount>3</TransactionCount>
    </HEADER>
    <EVENT>
        <EVENT_TYPE>AUD</EVENT_TYPE>
    </EVENT>
    <PROBATE>
        <Account>F04000178</Account>
        <Date>2005-04-18</Date>
    </PROBATE>
    <AUD>
        <Account>F04000178</Account>
        <Date>2005-04-18</Date>
    </AUD>
</TRANSACTION>

Thanks.
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
aozarovCommented:
That is probably because NodeList is a a "live list" and when you remove child it will effect its length and the get item by index.

Try this instead:
Pass to removeAll a Set -> Set toRemove =  new HashSet();
removeAll(toRemove, pXML, Node.ELEMENT_NODE, vParentNodeName) ;
// And then do this
for (Iterator i = toRemove.iterator(); i.hasNext(); )
{
Node node = (Node) i.next();
node.getParentNode().removeChild(node);
}      


public static void removeAll(Set toRemove, Node node, short nodeType, String name) {
    if (node.getNodeType() == nodeType &&
        (name == null || node.getNodeName().equals(name))) {
             toRemove.add(node);
    }
    else {
      // Visit the children
      NodeList list = node.getChildNodes();
      for (int i = 0; i < list.getLength(); i++) {
        removeAll(list.item(i), nodeType, name);
      }
    }
  }
0
 
trudyhlittleAuthor Commented:
Yep, that worked.  I had to make a slight correction to your example.  You forgot to include the toRemove set in the recursive call back to removeAll.  Thanks, a bunch.  I really appreciate the help.
0
 
aozarovCommented:
:-)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 4
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now