in xalan/src/main/java/org/apache/xalan/xsltc/runtime/BasisLibrary.java [1144:1298]
public static DTMAxisIterator nodeList2Iterator(
org.w3c.dom.NodeList nodeList,
Translet translet, DOM dom)
{
// First pass: build w3c DOM for all nodes not proxied from our DOM.
//
// Notice: this looses some (esp. parent) context for these nodes,
// so some way to wrap the original nodes inside a DTMAxisIterator
// might be preferable in the long run.
int n = 0; // allow for change in list length, just in case.
Document doc = null;
DTMManager dtmManager = null;
int[] proxyNodes = new int[nodeList.getLength()];
if (dom instanceof MultiDOM)
dtmManager = ((MultiDOM) dom).getDTMManager();
for (int i = 0; i < nodeList.getLength(); ++i) {
org.w3c.dom.Node node = nodeList.item(i);
if (node instanceof DTMNodeProxy) {
DTMNodeProxy proxy = (DTMNodeProxy)node;
DTM nodeDTM = proxy.getDTM();
int handle = proxy.getDTMNodeNumber();
boolean isOurDOM = (nodeDTM == dom);
if (!isOurDOM && dtmManager != null) {
try {
isOurDOM = (nodeDTM == dtmManager.getDTM(handle));
}
catch (ArrayIndexOutOfBoundsException e) {
// invalid node handle, so definitely not our doc
}
}
if (isOurDOM) {
proxyNodes[i] = handle;
++n;
continue;
}
}
proxyNodes[i] = DTM.NULL;
int nodeType = node.getNodeType();
if (doc == null) {
if (dom instanceof MultiDOM == false) {
runTimeError(RUN_TIME_INTERNAL_ERR, "need MultiDOM");
return null;
}
try {
AbstractTranslet at = (AbstractTranslet) translet;
doc = at.newDocument("", "__top__");
}
catch (javax.xml.parsers.ParserConfigurationException e) {
runTimeError(RUN_TIME_INTERNAL_ERR, e.getMessage());
return null;
}
}
// Use one dummy element as container for each node of the
// list. That way, it is easier to detect resp. avoid
// funny things which change the number of nodes,
// e.g. auto-concatenation of text nodes.
Element mid;
switch (nodeType) {
case org.w3c.dom.Node.ELEMENT_NODE:
case org.w3c.dom.Node.TEXT_NODE:
case org.w3c.dom.Node.CDATA_SECTION_NODE:
case org.w3c.dom.Node.COMMENT_NODE:
case org.w3c.dom.Node.ENTITY_REFERENCE_NODE:
case org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE:
mid = doc.createElementNS(null, "__dummy__");
mid.appendChild(doc.importNode(node, true));
doc.getDocumentElement().appendChild(mid);
++n;
break;
case org.w3c.dom.Node.ATTRIBUTE_NODE:
// The mid element also serves as a container for
// attributes, avoiding problems with conflicting
// attributes or node order.
mid = doc.createElementNS(null, "__dummy__");
mid.setAttributeNodeNS((Attr)doc.importNode(node, true));
doc.getDocumentElement().appendChild(mid);
++n;
break;
default:
// Better play it safe for all types we aren't sure we know
// how to deal with.
runTimeError(RUN_TIME_INTERNAL_ERR,
"Don't know how to convert node type "
+ nodeType);
}
}
// w3cDOM -> DTM -> DOMImpl
DTMAxisIterator iter = null, childIter = null, attrIter = null;
if (doc != null) {
final MultiDOM multiDOM = (MultiDOM) dom;
DOM idom = (DOM)dtmManager.getDTM(new DOMSource(doc), false,
null, true, false);
// Create DOMAdapter and register with MultiDOM
DOMAdapter domAdapter = new DOMAdapter(idom,
translet.getNamesArray(),
translet.getUrisArray(),
translet.getTypesArray(),
translet.getNamespaceArray());
multiDOM.addDOMAdapter(domAdapter);
DTMAxisIterator iter1 = idom.getAxisIterator(Axis.CHILD);
DTMAxisIterator iter2 = idom.getAxisIterator(Axis.CHILD);
iter = new AbsoluteIterator(
new StepIterator(iter1, iter2));
iter.setStartNode(DTMDefaultBase.ROOTNODE);
childIter = idom.getAxisIterator(Axis.CHILD);
attrIter = idom.getAxisIterator(Axis.ATTRIBUTE);
}
// Second pass: find DTM handles for every node in the list.
int[] dtmHandles = new int[n];
n = 0;
for (int i = 0; i < nodeList.getLength(); ++i) {
if (proxyNodes[i] != DTM.NULL) {
dtmHandles[n++] = proxyNodes[i];
continue;
}
org.w3c.dom.Node node = nodeList.item(i);
DTMAxisIterator iter3 = null;
int nodeType = node.getNodeType();
switch (nodeType) {
case org.w3c.dom.Node.ELEMENT_NODE:
case org.w3c.dom.Node.TEXT_NODE:
case org.w3c.dom.Node.CDATA_SECTION_NODE:
case org.w3c.dom.Node.COMMENT_NODE:
case org.w3c.dom.Node.ENTITY_REFERENCE_NODE:
case org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE:
iter3 = childIter;
break;
case org.w3c.dom.Node.ATTRIBUTE_NODE:
iter3 = attrIter;
break;
default:
// Should not happen, as first run should have got all these
throw new InternalRuntimeError("Mismatched cases");
}
if (iter3 != null) {
iter3.setStartNode(iter.next());
dtmHandles[n] = iter3.next();
// For now, play it self and perform extra checks:
if (dtmHandles[n] == DTMAxisIterator.END)
throw new InternalRuntimeError("Expected element missing at " + i);
if (iter3.next() != DTMAxisIterator.END)
throw new InternalRuntimeError("Too many elements at " + i);
++n;
}
}
if (n != dtmHandles.length)
throw new InternalRuntimeError("Nodes lost in second pass");
return new ArrayNodeListIterator(dtmHandles);
}