DranoMax
DranoMax

Reputation: 504

Grouping XML children together with XPath in Java

I've been searching everywhere but have yet to find a solution for my problem in Java.

I have an xml document that contains a Table of Contents for a book - abbreviated below.

<TOC>
  <USMARC>
    <Leader/>
      <VarFlds>
        <VarCFlds>
          <SSIFlds>
            <Fld970 I1="0" I2="1">
              <t>Acknowledgments</t>
              <p>p. ix</p>
            </Fld970>
            <Fld970 I1="1" I2="1">
              <t>Preface: The Generation</t>
              <p>p. 3</p>
            </Fld970>
            <Fld970 I1="1" I2="1">
              <l>Chapter 1</l>
              <t>The Duel</t>
              <p>p. 20</p>
            </Fld970>
            <Fld970 I1="1" I2="1">
              <l>Chapter 2</l>
              <t>The Dinner</t>
              <p>p. 48</p>
            </Fld970>
          </SSIFlds>
        </VarDFlds>
      </VarFlds>
    </USMARC>
  </Leader>
</TOC>

I need to be able to parse the XML into groups like so:

{[null, Acknowledgments, p. ix],[null, Preface: The Generation, p. 3],[Chapter 1, The Duel, p. 20],[Chapter 2, The Dinner, p. 48]}

(Note, that sometimes the child element [l] doesn't exist and should be replaced with null).

Currently I have:

 XPathExpression expr = xpath.compile("//TOC//SSIFlds/Fld970//text()");
        //evaluate expression result on XML document
        NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);

        for (int i = 0; i < nodes.getLength(); i++) {
            list.add(nodes.item(i).getNodeValue());
        }

But of course, this just grabs everything (that exists) and places it into one list... Is there any expression that can group everything like I want?

Upvotes: 0

Views: 335

Answers (1)

JLRishe
JLRishe

Reputation: 101730

You can't use a single XPath 1.0 expression to rearrange nodes into groups.

What you can do is actually select the Flt970 elements, iterate over those, and grab the elements inside them:

XPathExpression expr = xpath.compile("//TOC//SSIFlds/Fld970");
//evaluate expression result on XML document
NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);

for (int i = 0; i < nodes.getLength(); i++) {
    Element node = (Element)nodes.item(i);
    String l = getChildValue(node, "l"), 
           t = getChildValue(node, "t"), 
           p = getChildValue(node, "p");

    // use l, t, and p as needed
}

// defined elsewhere
private static String getChildValue(Element parent, String childName) {
    NodeList nodes = parent.getElementsByTagName(childName);
    return nodes.getLength() > 0 ? nodes.item(0).getTextContent() : "";
}

Upvotes: 1

Related Questions