kentcdodds kentcdodds - 1 month ago 9
Java Question

Get XML only immediate children elements by name

My question is: How can I get elements directly under a specific parent element when there are other elements with the same name as a "grandchild" of the parent element.

I'm using the Java DOM library to parse XML Elements and I'm running into trouble. Here's some (a small portion) of the xml I'm using:

<notifications>
<notification>
<groups>
<group name="zip-group.zip" zip="true">
<file location="C:\valid\directory\" />
<file location="C:\another\valid\file.doc" />
<file location="C:\valid\file\here.txt" />
</group>
</groups>
<file location="C:\valid\file.txt" />
<file location="C:\valid\file.xml" />
<file location="C:\valid\file.doc" />
</notification>
</notifications>


As you can see, there are two places you can place the
<file>
element. Either in groups or outside groups. I really want it structured this way because it's more user-friendly.

Now, whenever I call
notificationElement.getElementsByTagName("file");
it gives me all the
<file>
elements, including those under the
<group>
element. I handle each of these kinds of files differently, so this functionality is not desirable.

I've thought of two solutions:


  1. Get the parent element of the file element and deal with it accordingly (depending on whether it's
    <notification>
    or
    <group>
    .

  2. Rename the second
    <file>
    element to avoid confusion.



Neither of those solutions are as desirable as just leaving things the way they are and getting only the
<file>
elements which are direct children of
<notification>
elements.

I'm open to IMPO comments and answers about the "best" way to do this, but I'm really interested in DOM solutions because that's what the rest of this project is using. Thanks.

Answer

Well, the DOM solution to this question is actually pretty simple, even if it's not too elegant When I iterate through the filesNodeList which is returned when I call notificationElement.getElementsByTagName("file"); I just check whether the parent node's name is "notification." If it isn't then I ignore it because that will be handled by the <group> element. Here's my code solution:

for (int j = 0; j < filesNodeList.getLength(); j++) {
  Element fileElement = (Element) filesNodeList.item(j);
  if (!fileElement.getParentNode().getNodeName().equals("notification")) {
    continue;
  }
  ...
}