public static DTMAxisIterator nodeList2Iterator()

in src/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);
    }