A DESCRIPTION OF THE REQUEST :
This is an RFE for a class in the javax.xml.* packages.
XPath queries of the type "./@attr[1]" which are asking for "the attribute named 'attr' on the current node' are very inefficient using the XPath API. As an order of magnitude, it takes approximately 5 seconds to perform such a search in a 1,000 element loop (with a pre-compiled expression) whereas it takes almost no CPU time at all to access the Node API directly to obtain the attribute information.
JUSTIFICATION :
The query is a valid XPath expression and there is no reason why it should be inefficient in this implementation.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Performance from a compiled expression to be on-par with Node.getAttributes().getNamedItem("attr").getValue()
ACTUAL -
Orders of magnitude worse performance.
---------- BEGIN SOURCE ----------
// NOTE: XML input required!
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class Scratch {
private final XPathFactory xPathFactory = XPathFactory.newInstance();
/**
* @param xml
* @throws javax.xml.xpath.XPathExpressionException
*/
public void parse(Document xml) throws XPathExpressionException {
XPath xPath = xPathFactory.newXPath();
// skipping this for now because it involves our own implementation because
// SUN decided not to ship even a simple HashMap<String, String> implementation
// xPath.setNamespaceContext(myNsContext);
XPathExpression x1 = xPath.compile("./@attr1[1]");
XPathExpression x2 = xPath.compile("./@attr2[1]");
XPathExpression x3 = xPath.compile("./@attr3[1]");
XPathExpression x4 = xPath.compile("./@attr4[1]");
NodeList entities = (NodeList) xPath.evaluate("./MyNode", xml, XPathConstants.NODESET);
// there are typically 1,000 of these...
for (int i = 0 ; i < entities.getLength() ; i++){
Node entity = entities.item(i);
String attr1 = x1.evaluate(entity);
String attr2 = x2.evaluate(entity);
String attr3 = x3.evaluate(entity);
String attr4 = x4.evaluate(entity);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
be aware that queries of this type are inefficient and instead use null-handling code similar to the following
String attr = null;
NamedNodeMap attrs = node.getAttributes();
if (attrs != null){
Node item = attrs.getNamedItem("attr");
if (item != null)
attr = item.getValue();
}
This is an RFE for a class in the javax.xml.* packages.
XPath queries of the type "./@attr[1]" which are asking for "the attribute named 'attr' on the current node' are very inefficient using the XPath API. As an order of magnitude, it takes approximately 5 seconds to perform such a search in a 1,000 element loop (with a pre-compiled expression) whereas it takes almost no CPU time at all to access the Node API directly to obtain the attribute information.
JUSTIFICATION :
The query is a valid XPath expression and there is no reason why it should be inefficient in this implementation.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Performance from a compiled expression to be on-par with Node.getAttributes().getNamedItem("attr").getValue()
ACTUAL -
Orders of magnitude worse performance.
---------- BEGIN SOURCE ----------
// NOTE: XML input required!
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class Scratch {
private final XPathFactory xPathFactory = XPathFactory.newInstance();
/**
* @param xml
* @throws javax.xml.xpath.XPathExpressionException
*/
public void parse(Document xml) throws XPathExpressionException {
XPath xPath = xPathFactory.newXPath();
// skipping this for now because it involves our own implementation because
// SUN decided not to ship even a simple HashMap<String, String> implementation
// xPath.setNamespaceContext(myNsContext);
XPathExpression x1 = xPath.compile("./@attr1[1]");
XPathExpression x2 = xPath.compile("./@attr2[1]");
XPathExpression x3 = xPath.compile("./@attr3[1]");
XPathExpression x4 = xPath.compile("./@attr4[1]");
NodeList entities = (NodeList) xPath.evaluate("./MyNode", xml, XPathConstants.NODESET);
// there are typically 1,000 of these...
for (int i = 0 ; i < entities.getLength() ; i++){
Node entity = entities.item(i);
String attr1 = x1.evaluate(entity);
String attr2 = x2.evaluate(entity);
String attr3 = x3.evaluate(entity);
String attr4 = x4.evaluate(entity);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
be aware that queries of this type are inefficient and instead use null-handling code similar to the following
String attr = null;
NamedNodeMap attrs = node.getAttributes();
if (attrs != null){
Node item = attrs.getNamedItem("attr");
if (item != null)
attr = item.getValue();
}