本文以解析Mybatis config配置文件中"/configuration"元素为例进行说明Mybatis是如何进行sax解析工作的。
Mybatis配置文件解析流程图
时序图
相关源码
/** XMLConfigBuilder.java */
// 以解析Mybatis config配置文件"/configuration"元素为例说明sax解析机制:
parser.evalNode("/configuration");
/** XPathParser.java */
// 解析"/configuration"根节点为XNode
public XNode evalNode(String expression) {
return evalNode(document, expression);
}
public XNode evalNode(Object root, String expression) {
// NODE = new QName("http://www.w3.org/1999/XSL/Transform", "NODE");
// 解析"/configuration"根节点为Node
Node node = (Node) evaluate(expression, root, XPathConstants.NODE);
if (node == null) {
return null;
}
// 包装为XNode
return new XNode(this, node, variables);
}
// 利用Xpath类解析
private Object evaluate(String expression, Object root, QName returnType) {
try {
return xpath.evaluate(expression, root, returnType);
} catch (Exception e) {
throw new BuilderException("Error evaluating XPath. Cause: " + e, e);
}
}
/** XPathImpl.java */
// XPathImpl解析实现
public Object evaluate(String expression, Object item, QName returnType)
throws XPathExpressionException {
if ( expression == null ) {
String fmsg = XSLMessages.createXPATHMessage(
XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
new Object[] {"XPath expression"} );
throw new NullPointerException ( fmsg );
}
if ( returnType == null ) {
String fmsg = XSLMessages.createXPATHMessage(
XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
new Object[] {"returnType"} );
throw new NullPointerException ( fmsg );
}
// Checking if requested returnType is supported. returnType need to
// be defined in XPathConstants
if ( !isSupported ( returnType ) ) {
String fmsg = XSLMessages.createXPATHMessage(
XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
new Object[] { returnType.toString() } );
throw new IllegalArgumentException ( fmsg );
}
try {
// Xpath实际解析
XObject resultObject = eval( expression, item );
// 返回Node节点
return getResultAsType( resultObject, returnType );
} catch ( java.lang.NullPointerException npe ) {
// If VariableResolver returns null Or if we get
// NullPointerException at this stage for some other reason
// then we have to reurn XPathException
throw new XPathExpressionException ( npe );
} catch ( javax.xml.transform.TransformerException te ) {
Throwable nestedException = te.getException();
if ( nestedException instanceof javax.xml.xpath.XPathFunctionException ) {
throw (javax.xml.xpath.XPathFunctionException)nestedException;
} else {
// For any other exceptions we need to throw
// XPathExpressionException ( as per spec )
throw new XPathExpressionException ( te );
}
}
}
private XObject eval(String expression, Object contextItem)
throws javax.xml.transform.TransformerException {
// 构造XPath
com.sun.org.apache.xpath.internal.XPath xpath = new com.sun.org.apache.xpath.internal.XPath( expression,
null, prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT );
com.sun.org.apache.xpath.internal.XPathContext xpathSupport = null;
if ( functionResolver != null ) {
JAXPExtensionsProvider jep = new JAXPExtensionsProvider(
functionResolver, featureSecureProcessing, featureManager );
xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext( jep );
} else {
xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext();
}
XObject xobj = null;
xpathSupport.setVarStack(new JAXPVariableStack(variableResolver));
// If item is null, then we will create a a Dummy contextNode
if ( contextItem instanceof Node ) {
// 实例利用XPath解析xml元素为Node节点
xobj = xpath.execute (xpathSupport, (Node)contextItem,
prefixResolver );
} else {
xobj = xpath.execute ( xpathSupport, DTM.NULL, prefixResolver );
}
return xobj;
}
// 根据返回的解析类型获取结果
private Object getResultAsType( XObject resultObject, QName returnType )
throws javax.xml.transform.TransformerException {
// XPathConstants.STRING
if ( returnType.equals( XPathConstants.STRING ) ) {
return resultObject.str();
}
// XPathConstants.NUMBER
if ( returnType.equals( XPathConstants.NUMBER ) ) {
return new Double ( resultObject.num());
}
// XPathConstants.BOOLEAN
if ( returnType.equals( XPathConstants.BOOLEAN ) ) {
return new Boolean( resultObject.bool());
}
// XPathConstants.NODESET ---ORdered, UNOrdered???
if ( returnType.equals( XPathConstants.NODESET ) ) {
return resultObject.nodelist();
}
// XPathConstants.NODE
// 返回Node节点
if ( returnType.equals( XPathConstants.NODE ) ) {
NodeIterator ni = resultObject.nodeset();
//Return the first node, or null
return ni.nextNode();
}
String fmsg = XSLMessages.createXPATHMessage(
XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
new Object[] { returnType.toString()});
throw new IllegalArgumentException( fmsg );
}
/** XNode.java */
// XNode构造函数
public XNode(XPathParser xpathParser, Node node, Properties variables) {
this.xpathParser = xpathParser;
this.node = node;
this.name = node.getNodeName();
this.variables = variables;
// 获取node节点的属性Properties
this.attributes = parseAttributes(node);
// 获取node节点的Content
this.body = parseBody(node);
}