Dom4J配合XPath解析schema約束的xml配置文件問題
阿新 • • 發佈:2019-04-26
ali sel tex publish string exceptio xml文件 exc hashmap
如果一個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~
Dom4J配合XPath解析schema約束的xml配置文件問題