关于DOM4J的Namespace的问题(XPath)
2009-08-29 09:16
大家经常运用DOM4J操作XML文档,如果XML文档存在namespace的话,读写XML经常不工作,解决方案很简单的:
举个例子吧: 比如我一个XML文件头是这样的: <?xml version="1.0"?> <scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" initialstate="coordinator"> 请注意这个xml文件是带了namespace的, 读写这个xml要如下操作: SAXReader reader = new SAXReader(); Map map = new HashMap(); map.put("scxml","http://www.w3.org/2005/07/scxml"); reader.getDocumentFactory().setXPathNamespaceURIs(map); InputStream is = servletContext.getResourceAsStream("xxxx"); Document document = reader.read(is); 在操作任何节点的时候,你的XPath必须都要加上Namespace,以下都是可行的XPath表达式: String strXPath = "//scxml:state[@id='member_init']"; String strXPath = "/scxml:*[name()='scxml']/scxml:*[name()='datamodel']/scxml:data/@name"; String strXPath = "/scxml:*[name()='scxml']/scxml:*[name()='state']/scxml:*[name()='state' and @id='member_init']/scxml:transition"; List list = document.selectNodes(strXPath); 看到没有,所有的//和/后面都要加上"scxml:"(节点属性前面不要加) . 第一个表达式是要找文档里面id为'member_init'的state节点 第二个表达式是找name属性,这个name属性的有这样的祖先链/scxml/datamodel/data 第三个也没什么了,跟找节点transition,并对它的祖先链有所要求 例如还要注意一下,你从Node api调用getPath()或者getUniquePath(),得到的XPath,是不带Namespace的,所以你要做如下处理: public static final String XMLNS = "scxml"; String oriNodePath = node.getPath(); String xPath = null; xPath = oriNodePath.replaceAll("/", "/"+XMLNS+":"); return xPath; 这样处理过的xPath才能被Document.select, Node.select函数处理 当然这里你也要小心的对属性元素区别处理,因为属性名前是不带namespace的. |