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());
}
}
}

结果为:

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

我们会发现,同样的代码,运行在引入了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());
}
}
}

运行结果:

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

Perfect~

上一篇:JavaWeb(七)之详解JavaWeb路径


下一篇:201671010140. 2016-2017-2 《Java程序设计》java学习第三周