I have an xml containing the log of 1000 events where each one has a key, My objective is when a user search for an event key, i should display him the xml of the event node having this key and prepare the info of the previous and next sibling.
The xml structure is as follow:
<LOG>
<EVENT_SET>
<DOCGET system="T610_00" fingerPrint="NO_SIGNATURE">
<event>
<key>382</key>
<date>2015-01-28T09:15:15.350+0000</date>
<service>CORE</service>
<class>APPLICATION</class>
</event>
<document>
<docuri>getdocs:///DocMapCSDOCS.dPortal/1</docuri>
<sign_info>
<signature>VqtR9Gpny/MPE43/5o4hJXp8bR7gbsVUJqHlTI+VfztMSQecTpZwAQpxmorrdBJKvmn+h7eZzV1geVodkVECvOjQMRmRbnpT6mrpbiXxjDOsZsQRDNemTYUKETrQFIBRtXcjoP61une1LOsS5C749ehwbZ1jEaNH6fPjH4n+OH4=</signature>
</sign_info>
</document>
</DOCGET>
<DOCGET system="T610_00" fingerPrint="NO_SIGNATURE">
<event>
<key>383</key>
<date>2015-01-28T09:15:18.310+0000</date>
<service>CORE</service>
<class>APPLICATION</class>
</event>
<document>
<docuri>getdocs:///DocMapCSDOCS.dPortal/2</docuri>
<sign_info>
<signature>VqtR9Gpny/MPE43/5o4hJXp8bR7gbsVUJqHlTI+VfztMSQecTpZwAQpxmorrdBJKvmn+h7eZzV1geVodkVECvOjQMRmRbnpT6mrpbiXxjDOsZsQRDNemTYUKETrQFIBRtXcjoP61une1LOsS5C749ehwbZ1jEaNH6fPjH4n+OH4=</signature>
</sign_info>
</document>
</DOCGET>
.......
</EVENT_SET>
</LOG>
And my code till now to get the node of a key is:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false);
DocumentBuilder builder = factory.newDocumentBuilder();
//parsing the xml file
journaldoc = builder.parse(journalFile);
XPathFactory xpathfactory = XPathFactory.newInstance();
XPath xpath = xpathfactory.newXPath();
//xpath to search for the event having the key requated by the user
String sXpath = "//DOCGET[event/key='"+eventkey+"']";
XPathExpression expr = xpath.compile(sXpath);
Object result = expr.evaluate(journaldoc, XPathConstants.NODE);
Node eventnode = (Node) result;
//return to the user the xml part with root DOCGET, and having the key requested
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Node copyNode = document.importNode(eventNode, true);
document.appendChild(copyNode);
DOMImplementationLS domImplementationLS = (DOMImplementationLS) document.getImplementation();
LSSerializer lsSerializer = domImplementationLS.createLSSerializer();
String xmlNode = lsSerializer.writeToString(document);
Now i need to get the previous and next sibling of this node and get their keys in order to save them in a HashMap.
The problem is when doing eventnode.getPreviousSibling and eventnode.getNextSibling , i am getting corrupted info and i am not able to get the key of these events.
Does anyone has a better idea to do this?
Thank you, Karine
I think you are looking for the XPath axis preceding-sibling
and following-sibling
. These select all nodes at the same level, so if you just want the next neighbors, you need to add a predicate to select just the first: following-sibling::*[1]
. But you want only event nodes and the event nodes are not directly siblins, but the <DOCGET>
elements are. So from an event node you need to go up, find the next/previous sibling and go down again. This boils down to this expression: ../preceding-sibling::*[1]/event
to be evaluated on an event node.
You can ease the task by using data projection (Disclosure: I'm affiliated with that project) to have a object oriented access to the events, but still decouple the Java code structure from the XML structure:
public class ReadEvents {
public interface Event {
@XBRead("./key")
String getKey();
@XBRead("./date using yyyy-MM-dd'T'HH:mm:ss.SSSZ")
Date getDate();
@XBRead("../document/docuri")
String getDocumentURI();
@XBRead("../preceding-sibling::*[1]/event")
Event getPreviousEvent();
@XBRead("../following-sibling::*[1]/event")
Event getNextEvent();
}
public static void main(String... args) {
List<Event> allEvents = new XBProjector().io().url("res://log.xml").evalXPath("//event").asListOf(Event.class);
for (Event event : allEvents) {
System.out.print(event.getDate()+ ": Event " + event.getKey());
if (event.getPreviousEvent() != null) {
System.out.print(" previous event has key " + event.getPreviousEvent().getKey());
}
if (event.getNextEvent() != null) {
System.out.print(" next event has key " + event.getNextEvent().getKey());
}
System.out.println();
}
}
}
For your example, this program prints out:
Wed Jan 28 10:15:15 CET 2015: Event 382 next event has key 383
Wed Jan 28 10:15:18 CET 2015: Event 383 previous event has key 382