xpathutil.java

来自「jakarta-taglibs」· Java 代码 · 共 888 行 · 第 1/3 页

JAVA
888
字号
     * To evaluate an XPath expression using Xalan, we need 
     * to create an XPath object, which wraps an expression object and provides 
     * general services for execution of that expression.
     *
     * An XPath object can be instantiated with the following information:
     *     - XPath expression to evaluate
     *     - SourceLocator 
     *        (reports where an error occurred in the XML source or 
     *        transformation instructions)
     *     - PrefixResolver
     *        (resolve prefixes to namespace URIs)
     *     - type
     *        (one of SELECT or MATCH)
     *     - ErrorListener
     *        (customized error handling)
     *
     * Execution of the XPath expression represented by an XPath object
     * is done via method execute which takes the following parameters:
     *     - XPathContext 
     *        The execution context
     *     - Node contextNode
     *        The node that "." expresses
     *     - PrefixResolver namespaceContext
     *        The context in which namespaces in the XPath are supposed to be 
     *        expanded.
     *
     * Given all of this, if no context node is set for the evaluation
     * of the XPath expression, one must be set so Xalan 
     * can successfully evaluate a JSTL XPath expression.
     * (it will not work if the context node is given as a varialbe
     * at the beginning of the expression)
     *
     * @@@ Provide more details...
     */
    protected Node adaptParamsForXalan( JstlVariableContext jvc,  Node n,
    String xpath ) {
        Node boundDocument = null;
        
        modifiedXPath = xpath;
        String origXPath = xpath ;
        boolean whetherOrigXPath = true;
        
        // If contextNode is not null then  just pass the values to Xalan XPath
        if ( n != null ) {
            return n;
        }
        
        if (  xpath.startsWith("$")  ) {
            // JSTL uses $scopePrefix:varLocalName/xpath expression

            String varQName=  xpath.substring( xpath.indexOf("$")+1);
            if ( varQName.indexOf("/") > 0 ) {
                varQName = varQName.substring( 0, varQName.indexOf("/"));
            }
            String varPrefix =  null;
            String varLocalName =  varQName;
            if ( varQName.indexOf( ":") >= 0 ) {
                varPrefix = varQName.substring( 0, varQName.indexOf(":") );
                varLocalName = varQName.substring( varQName.indexOf(":")+1 );
            }
            
            if ( xpath.indexOf("/") > 0 ) {
                xpath = xpath.substring( xpath.indexOf("/"));
            } else  {
                xpath = "/*";
                whetherOrigXPath = false; 
            }
           
            
            try {
                Object varObject=jvc.getVariableValue( null,varPrefix,
                varLocalName);
                //System.out.println( "varObject => : its Class " +varObject +
                // ":" + varObject.getClass() );
                
                if ( Class.forName("org.w3c.dom.Document").isInstance(
                varObject ) )  {
                    //boundDocument = ((Document)varObject).getDocumentElement();
                    boundDocument = ((Document)varObject);
                } else {
                    
                    //System.out.println("Creating a Dummy document to pass " +
                    // " onto as context node " );
                    
                    if ( Class.forName("org.apache.taglibs.standard.tag.common.xml.JSTLNodeList").isInstance( varObject ) ) {
                        Document newDocument = getDummyDocument();

                        JSTLNodeList jstlNodeList = (JSTLNodeList)varObject;
                        if   ( jstlNodeList.getLength() == 1 ) { 
                            if ( Class.forName("org.w3c.dom.Node").isInstance(
                                jstlNodeList.elementAt(0) ) ) { 
                                Node node = (Node)jstlNodeList.elementAt(0);
                                boundDocument = getDocumentForNode(node);
                                if ( whetherOrigXPath ) {
                                    xpath="/*" + xpath;
                                }

                            } else {

                                //Nodelist with primitive type
                                Object myObject = jstlNodeList.elementAt(0);

                                //p("Single Element of primitive type");
                                //p("Type => " + myObject.getClass());

                                xpath = myObject.toString();

                                //p("String value ( xpathwould be this) => " + xpath);
                                boundDocument = newDocument;
                            } 
                            
                        } else {

                            Element dummyroot = newDocument.getDocumentElement();
                            for ( int i=0; i< jstlNodeList.getLength(); i++ ) {
                                Node currNode = (Node)jstlNodeList.item(i);
                            
                                Node importedNode = newDocument.importNode(
                                    currNode, true );

                                //printDetails ( newDocument);

                                dummyroot.appendChild( importedNode );

                                //p( "Details of the document After importing");
                                //printDetails ( newDocument);
                            }
                            boundDocument = newDocument;
                            // printDetails ( boundDocument );
                            //Verify :As we are adding Document element we need
                            // to change the xpath expression.Hopefully this
                            // won't  change the result

                            xpath = "/*" +  xpath;
                        }
                    } else if ( Class.forName("org.w3c.dom.Node").isInstance(
                    varObject ) ) {
                        boundDocument = getDocumentForNode((Node)varObject);
                        if (whetherOrigXPath) {
                            xpath = "/*" + xpath;
                        }
                    } else {
                        boundDocument = getDummyDocument();
                        xpath = origXPath;
                    }
                    
                    
                }
            } catch ( UnresolvableException ue ) {
                // FIXME: LOG
                System.out.println("Variable Unresolvable :" + ue.getMessage());
                ue.printStackTrace();
            } catch ( ClassNotFoundException cnf ) {
                // Will never happen
            }
        } else { 
            //System.out.println("Not encountered $ Creating a Dummydocument 2 "+
             //   "pass onto as context node " );
            boundDocument = getDummyDocument();
        }
     
        modifiedXPath = xpath;
        //System.out.println("Modified XPath::boundDocument =>" + modifiedXPath +
        //    "::" + boundDocument );
         
        return boundDocument;
    }
    

    //*********************************************************************
    // 
    
    /**
     ** @@@ why do we have to pass varVector in the varStack first, and then
     * to XPath object?
     */
    private Vector fillVarStack(JstlVariableContext vs, XPathContext xpathSupport) 
    throws JspTagException {
        org.apache.xpath.VariableStack myvs = xpathSupport.getVarStack();
        Vector varVector = getVariableQNames();
        for ( int i=0; i<varVector.size(); i++ ) {
          
            QName varQName = (QName)varVector.elementAt(i);

            try { 
                XObject variableValue = vs.getVariableOrParam( xpathSupport, varQName );
                //p("&&&&Variable set to => " + variableValue.toString() );
                //p("&&&&Variable type => " + variableValue.getTypeString() );
                myvs.setGlobalVariable( i, variableValue );

            } catch ( TransformerException te ) {
                throw new JspTagException(te.toString(), te);
            } 
 
        }
        return varVector;
    }
        
    
    
    
    
    //*********************************************************************
    // Static support for context retrieval from parent <forEach> tag
    
    public static Node getContext(Tag t) throws JspTagException {
        ForEachTag xt =
        (ForEachTag) TagSupport.findAncestorWithClass(
        t, ForEachTag.class);
        if (xt == null)
            return null;
        else
            return (xt.getContext());
    }
    
    //*********************************************************************
    // Utility methods
    
    private static void p(String s) {
        System.out.println("[XPathUtil] " + s);
    }
    
    public static void printDetails(Node n) {
        System.out.println("\n\nDetails of Node = > " + n ) ;
        System.out.println("Name:Type:Node Value = > " + n.getNodeName() +
        ":" + n.getNodeType() + ":" + n.getNodeValue()  ) ;
        System.out.println("Namespace URI : Prefix : localName = > " +
        n.getNamespaceURI() + ":" +n.getPrefix() + ":" + n.getLocalName());
        System.out.println("\n Node has children => " + n.hasChildNodes() );
        if ( n.hasChildNodes() ) {
            NodeList nl = n.getChildNodes();
            System.out.println("Number of Children => " + nl.getLength() );
            for ( int i=0; i<nl.getLength(); i++ ) {
                Node childNode = nl.item(i);
                printDetails( childNode );
            }
        }
    }    
}

class JSTLNodeList extends Vector implements NodeList   {
    
    Vector nodeVector;

    public JSTLNodeList ( Vector nodeVector ) {
        this.nodeVector = nodeVector;
    }

    public JSTLNodeList ( NodeList nl ) {
        nodeVector = new Vector();
        //System.out.println("[JSTLNodeList] nodelist details");
        for ( int i=0; i<nl.getLength(); i++ ) {
            Node currNode = nl.item(i);
            //XPathUtil.printDetails ( currNode );
            nodeVector.add(i, nl.item(i) );
        }
    }

    public JSTLNodeList ( Node n ) {
        nodeVector = new Vector();
        nodeVector.addElement( n );
    }
        

    public Node item ( int index ) {
        return (Node)nodeVector.elementAt( index );
    }

    public Object elementAt ( int index ) {
        return nodeVector.elementAt( index );
    }

    public Object get ( int index ) {
        return nodeVector.get( index );
    }

    public int getLength (  ) {
        return nodeVector.size( );
    }

    public int size (  ) {
        //System.out.println("JSTL node list size => " + nodeVector.size() );
        return nodeVector.size( );
    }

    // Can implement other Vector methods to redirect those methods to 
    // the vector in the variable param. As we are not using them as part 
    // of this implementation we are not doing that here. If this changes
    // then we need to override those methods accordingly  

}
         



⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?