TreeInfo.selectId() to select element by ID efficiently
Added by Marc Dzaebel over 8 years ago
Hi,
in my Java program with Saxon 9-7, I need to find an element with ID attribute (without prefix) set to a certain value. While there are slow XPath methods like "//*[@ID='" + refID + "']", or "id(...)" there is a selectID method on TreeInfo, that seems to be more efficient but it returns null.
Input:
Program: nodeInfo.getTreeInfo().selectID("1", false); // returns null
I know, there must be a DTD that defines the attribute as being of type ID and the parser must be capable. However, without having a DTD, is it possible to get the element efficiently and how?
Thanks, Marc
Replies (4)
Please register to reply
RE: TreeInfo.selectId() to select element by ID efficiently - Added by Michael Kay over 8 years ago
From your description, I assume there is nothing special about the ID attribute - the fact that it's name is "ID" obviously does not make it any different from any other attribute. Looking at the Saxon facilities for finding attributes of type ID isn't going to help if your ID attribute isn't an ID attribute, so to speak...
Assuming you are doing this often enough to justify the cost of building an index, then my suggestion would be to create a Java map.
Map map = new HashMap<>(); QName id = new QName("ID"); for (XdmItem n : xpathCompiler.evaluate("//*[@ID]") { XdmNode node = (XdmNode)n; map.put(n.getAttributeValue(id), node); };
and then you can find nodes using the ID by looking in this map.
I can think of other techniques, e.g. building an XDM map rather than a Java map, but they will be a lot less efficient because they involve an XPath execution to find each ID value.
If you aren't doing this repeatedly, i.e. you only want to find one ID value, then the linear search is going to be the best method available.
Incidentally, if you need to evaluate something like @//[@ID = XXXX]@ repeatedly with different values of XXXX, then it's not a good idea to build the XPath expression by string concatenation. Remember that compiling an XPath expression usually costs much more than executing it. So compile the expression @//[@ID = $x]@ once, and then evaluate it repeatedly with different values of $x.
RE: TreeInfo.selectId() to select element by ID efficiently - Added by Marc Dzaebel over 8 years ago
Great and helpfull answer,
in fact I have to use an XPathVariableResolver.
Thanks, Marc
RE: TreeInfo.selectId() to select element by ID efficiently - Added by Michael Kay over 8 years ago
I'd recommend using the s9api interface for XPath evaluation, rather than the JAXP interface, because of its type safety, and its ability to handle the full XPath 2.0/3.0 data model, including for example maps and arrays.
RE: TreeInfo.selectId() to select element by ID efficiently - Added by Marc Dzaebel over 8 years ago
Thanks a lot! I'll change it.
Please register to reply