关于DOM4J的Namespace的问题

  大家经常运用DOM4J操作XML文档,如果XML文档存在namespace的话,读写XML经常不工作,解决方案很简单的:

举个例子吧:

比如我一个XML文件头是这样的:


        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的.

 
 


你可能感兴趣的:(关于DOM4J的Namespace的问题)