我们如果想解析xml文件,我们指定是想获取xml中的内容,xml是数据展现和存储的一种方式,但是,我们需要在java中使用,不可能每次都要去解析xml的语法,我们要做的就是解析一次,形成java的xml的数据对象,这也是两种不同的数据形式的转换工作。XNode是mybatis自己构造的一个区别于jdk自身提供的Node的一个增强类,不过mybatis采用的是组合方式实现,没有采用继承,秉承了一般的编程规则,组合优先。
XNode做了一下几件事情
第一件:获取父亲,儿子
第二件:获取一个Node中的属性和对应的值
第三件:获取指定的name和value的值,这个应该是mybatis自己需要的属性
/** * Created by liuxu on 16-5-28. * 这个是mybatis的封装了jdk原有的Node的对象,自己构造出来的,这样子,自己以后的使用中会很方便,不用来回的切换了 * <p> * 这个是xml文件中一个节点的详细信息(注意:mybatis只会解析xml文件,就是只会读取,不会写入) */ public class XNode { /** * 还好都是jdk本身的工具类,只有最后一个解析xml的基础工具类是mybatis的io的 */ private Node node; private String name; private String body; private Properties attributes; private Properties variables; private XPathParser xpathParser; /** * 使用解析器构造XNode对象,感觉这个对象是一个dom对象,只有一个对象,因为一个xml最好还是个一个dom树最好 * * @param xpathParser xml解析 * @param node 节点 * @param variables 属性节点 */ public XNode(XPathParser xpathParser, Node node, Properties variables) { this.xpathParser = xpathParser; this.node = node; this.name = node.getNodeName(); this.variables = variables; this.attributes = parseAttributes(node); this.body = parseBody(node); } /** * 构造一个信息的XNode节点(保存在内存中 ) * * @param node jdk的一般普通节点,也就是document返回的Node对象,自己进行封装一下 * @return */ public XNode newXNode(Node node) { return new XNode(xpathParser, node, variables); } /** * 获取XNode的父亲(双亲),还是使用原始的node的操作,之后转化成XNode * * @return 父亲的XNode对象 */ public XNode getParent() { Node parent = node.getParentNode(); if (parent == null || !(parent instanceof Element)) { return null; } else { return new XNode(xpathParser, parent, variables); } } /** * 获取路径,是xml中的标签的路径 * * @return 路径 */ public String getPath() { StringBuilder builder = new StringBuilder(); Node current = node; while (current != null && current instanceof Element) { if (current != node) { builder.insert(0, "/"); } builder.insert(0, current.getNodeName()); current = current.getParentNode(); } return builder.toString(); } /** * 不明白是干什么的,反正是觉得应该是mybatis自己应用解析模式吧 * * @return */ public String getValueBasedIdentifier() { StringBuilder builder = new StringBuilder(); XNode current = this; while (current != null) { if (current != this) { builder.insert(0, "_"); } String value = current.getStringAttribute("id", current.getStringAttribute("value", current.getStringAttribute("property", null))); if (value != null) { value = value.replace('.', '_'); /** * 注意StringBuilder使用的插入模式,好像这个是的动态的字符串,,可以随便的插入和删除操作,很方便 */ builder.insert(0, "]"); builder.insert(0, value); builder.insert(0, "["); } builder.insert(0, current.getName()); current = current.getParent(); } return builder.toString(); } /** * 下面是引用XPathParse的一些解析方法 * * @param expression 解析的表达式 * @return 解析之后的值 */ public String evalString(String expression) { return xpathParser.evalString(node, expression); } public Boolean evalBoolean(String expression) { return xpathParser.evalBoolean(node, expression); } public Double evalDouble(String expression) { return xpathParser.evalDouble(node, expression); } public List<XNode> evalNodes(String expression) { return xpathParser.evalNodes(node, expression); } public XNode evalNode(String expression) { return xpathParser.evalNode(node, expression); } public Node getNode() { return node; } public String getName() { return name; } public String getStringBody() { return getStringBody(null); } public String getStringBody(String def) { if (body == null) { return def; } else { return body; } } public Boolean getBooleanBody() { return getBooleanBody(null); } public Boolean getBooleanBody(Boolean def) { if (body == null) { return def; } else { return Boolean.valueOf(body); } } public Integer getIntBody() { return getIntBody(null); } public Integer getIntBody(Integer def) { if (body == null) { return def; } else { return Integer.parseInt(body); } } public Long getLongBody() { return getLongBody(null); } public Long getLongBody(Long def) { if (body == null) { return def; } else { return Long.parseLong(body); } } public Double getDoubleBody() { return getDoubleBody(null); } public Double getDoubleBody(Double def) { if (body == null) { return def; } else { return Double.parseDouble(body); } } public Float getFloatBody() { return getFloatBody(null); } public Float getFloatBody(Float def) { if (body == null) { return def; } else { return Float.parseFloat(body); } } public <T extends Enum<T>> T getEnumAttribute(Class<T> enumType, String name) { return getEnumAttribute(enumType, name, null); } public <T extends Enum<T>> T getEnumAttribute(Class<T> enumType, String name, T def) { String value = getStringAttribute(name); if (value == null) { return def; } else { return Enum.valueOf(enumType, value); } } public String getStringAttribute(String name) { return getStringAttribute(name, null); } /** * 获取attribute中的属性值 */ public String getStringAttribute(String name, String def) { String value = attributes.getProperty(name); if (value == null) { return def; } else { return value; } } /** * 下面都是应用getStringAttribute的方法获取的值 */ public Boolean getBooleanAttribute(String name) { return getBooleanAttribute(name, null); } public Boolean getBooleanAttribute(String name, Boolean def) { String value = attributes.getProperty(name); if (value == null) { return def; } else { return Boolean.valueOf(value); } } public Integer getIntAttribute(String name) { return getIntAttribute(name, null); } public Integer getIntAttribute(String name, Integer def) { String value = attributes.getProperty(name); if (value == null) { return def; } else { return Integer.parseInt(value); } } public Long getLongAttribute(String name) { return getLongAttribute(name, null); } public Long getLongAttribute(String name, Long def) { String value = attributes.getProperty(name); if (value == null) { return def; } else { return Long.parseLong(value); } } public Double getDoubleAttribute(String name) { return getDoubleAttribute(name, null); } public Double getDoubleAttribute(String name, Double def) { String value = attributes.getProperty(name); if (value == null) { return def; } else { return Double.parseDouble(value); } } public Float getFloatAttribute(String name) { return getFloatAttribute(name, null); } public Float getFloatAttribute(String name, Float def) { String value = attributes.getProperty(name); if (value == null) { return def; } else { return Float.parseFloat(value); } } /** * 获取孩子节点的List集合 * * @return list的node集合 */ public List<XNode> getChildren() { List<XNode> children = new ArrayList<XNode>(); NodeList nodeList = node.getChildNodes(); if (nodeList != null) { for (int i = 0, n = nodeList.getLength(); i < n; i++) { Node node = nodeList.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { children.add(new XNode(xpathParser, node, variables)); } } } return children; } /** * 获取孩子的属性当做属性配置 * * @return Properties */ public Properties getChildrenAsProperties() { Properties properties = new Properties(); for (XNode child : getChildren()) { String name = child.getStringAttribute("name"); String value = child.getStringAttribute("value"); if (name != null && value != null) { properties.setProperty(name, value); } } return properties; } /** * 给了一个toString方法,这样子,我能在显示的时候更加的友好 * * @return 字符串 */ @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("<"); builder.append(name); for (Map.Entry<Object, Object> entry : attributes.entrySet()) { builder.append(" "); builder.append(entry.getKey()); builder.append("=\""); builder.append(entry.getValue()); builder.append("\""); } List<XNode> children = getChildren(); if (!children.isEmpty()) { builder.append(">\n"); for (XNode node : children) { builder.append(node.toString()); } builder.append("</"); builder.append(name); builder.append(">"); } else if (body != null) { builder.append(">"); builder.append(body); builder.append("</"); builder.append(name); builder.append(">"); } else { builder.append("/>"); } builder.append("\n"); return builder.toString(); } /** * 获取这个节点的属性,就是你配置在这个节点中的属性,不是text内容(XNode并没有采用一种继承的策略,而是一种组合的关系,这样子最好了) * * @param n 节点 * @return 节点的属性内容 */ private Properties parseAttributes(Node n) { Properties attributes = new Properties(); /** * 获取Node之中的属性,然后是进行遍历属性获取内容 */ NamedNodeMap attributeNodes = n.getAttributes(); if (attributeNodes != null) { for (int i = 0; i < attributeNodes.getLength(); i++) { Node attribute = attributeNodes.item(i); String value = PropertyParser.parse(attribute.getNodeValue(), variables); attributes.put(attribute.getNodeName(), value); } } return attributes; } /** * 解析身体的东西,不知道干什么用,反正是递归的调用这个东西 * * @param node * @return */ private String parseBody(Node node) { String data = getBodyData(node); if (data == null) { NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); data = getBodyData(child); if (data != null) { break; } } } return data; } private String getBodyData(Node child) { if (child.getNodeType() == Node.CDATA_SECTION_NODE || child.getNodeType() == Node.TEXT_NODE) { String data = ((CharacterData) child).getData(); data = PropertyParser.parse(data, variables); return data; } return null; } }
感悟:使用组合慎用继承