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~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值