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 + -
显示快捷键?