Reputation: 504
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
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