• 管理
  • Dom4J配合XPath解析schema约束的xml配置文件问题

    如果一个xml文件没有引入约束,或者引入的是DTD约束时,那么使用dom4j和xpath是可以正常解析的,不引入约束的情况本文不再展示。

    引入DTD约束的情况

    • mybook.dtd:
    <?xml version="1.0" encoding="UTF-8" ?>
    <!ELEMENT books (book+)>
    <!ELEMENT book (name|author|price)+>
    <!ELEMENT name (#PCDATA)>
    <!ELEMENT author (#PCDATA)>
    <!ELEMENT price (#PCDATA)>
    <!ATTLIST book id ID #REQUIRED publish CDATA #IMPLIED>
    
    • book.xml:
    <?xml version="1.0" encoding="UTF-8 ?>
    <!DOCTYPE books SYSTEM "mybook.dtd">
    <books>
        <book id="_001">
            <name>西游记</name>
        </book>
        <book id="_002">
            <name>三国演义</name>
        </book>
        <book id="_003">
            <name>水浒传</name>
        </book>
        <book id="_004">
            <name>红楼梦</name>
        </book>
    </books>
    

    测试类:

    public class DemoBook {
        public static void main(String[] args) throws DocumentException {
            SAXReader reader = new SAXReader();
            Document document = reader.read(DemoBook.class.getResourceAsStream("book.xml"));
            List<Node> nodes = document.selectNodes("//name");
            for (Node node : nodes) {
                Element element = (Element) node;
                System.out.print(element.getText()+" ");
            }
        }
    }
    
    //输出结果:西游记 三国演义 水浒传 红楼梦 
    

    可见,引入了DTD约束的xml是可以通过dom4j和xpath表达式正常解析的.而引入Schema约束的时候呢?

    引入Schema约束的情况

    • mybook.xsd:
    <?xml version="1.0" encoding="UTF-8"?>
    <schema xmlns="http://www.w3.org/2001/XMLSchema"
    	targetNamespace="http://www.mytest.com/book"
    	elementFormDefault="qualified">
    	<element name="books">
    		<complexType>
    			<sequence maxOccurs="unbounded">
    				<element name="book">
    					<complexType>
    						<choice maxOccurs="unbounded">
    							<element name="name" type="string"></element>
    							<element name="author" type="string"></element>
    						</choice>
    					</complexType>
    				</element>
    			</sequence>
    		</complexType>
    	</element>
    </schema>
    
    • book.xml:
    <?xml version="1.0" encoding="UTF-8" ?>
    <books
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns="http://www.mytest.com/book"
            xsi:schemaLocation="http://www.mytest.com/book /mybook.xsd"
    >
        <book>
            <name>西游记</name>
        </book>
        <book>
            <name>三国演义</name>
        </book>
        <book>
            <name>水浒传</name>
        </book>
        <book>
            <name>红楼梦</name>
        </book>
    </books>
    

    测试类:

    public class DemoBook {
        public static void main(String[] args) throws DocumentException {
            SAXReader reader = new SAXReader();
            Document document = reader.read(DemoBook.class.getResourceAsStream("book.xml"));
            List<Node> nodes = document.selectNodes("//name");
            for (Node node : nodes) {
                Element element = (Element) node;
                System.out.println(element.getText());
            }
        }
    }
    

    结果为:

    我们会发现,同样的代码,运行在引入了Schema约束的xml文件上虽然正常运行了,但是并没有达到我们想要的结果,document对象获取到的nodes集合是个空集合[]

    产生问题的原因

    当XPath表达式中没有前缀时,查询的元素命名空间也应该是默认值,否则是查询不到结果的。引入了Schema约束的xml文件使用了命名空间,此时查询元素的命名空间不再是默认值了,所以此时的结果是个空集合。

    解决方案:

    此时如果想要正确的解析结果,必须设置命名空间后再对文档进行解析。

    修改后的测试类:

    public class DemoBook {
        public static void main(String[] args) throws DocumentException {
            SAXReader reader = new SAXReader();
            //声明一个map集合保存命名空间
            Map<String,String > map = new HashMap<>();
            //给命名空间取别名
            map.put("myNameSpace","http://www.mytest.com/book");
            //设置命名空间
            reader.getDocumentFactory().setXPathNamespaceURIs(map);
            //读取文档
            Document document = reader.read(Demo1.class.getResourceAsStream("book.xml"));
            List<Node> nodes = document.selectNodes("//myNameSpace:name");
            for (Node node : nodes) {
                Element element = (Element)node;
                System.out.println(element.getText());
            }
        }
    }
    

    运行结果:

    Perfect~

    posted @ 2019-04-25 22:25  故事而已zzz  阅读(492)  评论(0)    收藏  举报