POCO::XML(二) 简单读XML文档

时间:2021-04-19 12:04:23

先来看一下在Poco中XML各元素被抽象成什么关系:

POCO::XML(二) 简单读XML文档

可以看到,任何元素都被抽象成Node,同时又分为三种类型的节点。(Attr和Notation看成一种)

第一种类型:CharacterData,这类Node是Name不可变,而Value可以由用户自定义。

第二种类型:AbstractContainerNode,这类Node有个特点,即含有属性,特别的对于Element节点,Name可以由用户自定义,而Value不可变。

第三种类型:右边两个,它们既可以改变Name,也可以改变Value。

下面是sample.xml文本:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<!--
	This is a comment.
-->

<zhong>
	<guo long="5">hahah</guo>
</zhong>
对于上面这一份XML数据,有下面一份代码执行操作:

InputSource src("./sample.xml");//设置源数据
	try
	{
		DOMParser parser;//创建一个分析者
		AutoPtr<Document> pDoc = parser.parse(&src);//开始分析,并返回指向分析后数据的指针,用AutoPtr是为了自动回收垃圾
		NodeIterator it(pDoc, NodeFilter::SHOW_ALL);//创建一个节点迭代器,默认迭代显示全部node
		Node* pNode = it.nextNode();//此时指向第一个
		while (pNode)
		{
			NamedNodeMap* map = pNode->attributes();//试图返回这个节点的属性
			if(map)//看看是否真有属性
			{
				for(int i = 0 ; i < map->length() ; i++)//属性肯定至少0个,用循环一个个取出
				{
					Node* attr = map->item(i);
					std::cout << attr->nodeName() << std::endl;
					std::cout << attr->nodeValue() << std::endl;
				}//属性结束
			}
			std::cout << pNode->nodeName() << std::endl;//取出当前节点的Name
			std::cout<< pNode->nodeValue() << std::endl;//取出当前节点的Value
			pNode = it.nextNode();//指向下一个node
		}
	}
	catch (Exception& exc)
	{
		std::cerr << exc.displayText() << std::endl;
	}
可以看出,节点的Name和Value同节点属性的Name和Value取得方法是同样的,都是用nodeName()和nodeValue()。

看一下显示结果:

POCO::XML(二) 简单读XML文档
在把数据拿过来看看:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<!--
	This is a comment.
-->

<zhong>
	<guo long="5">hahah</guo>
</zhong>
可以看出,程序虽是我们写的,可是具体的遍历行为却是Poco自己定义的。首先明确,有#的全都是系统的const string,也就体现了Name不可变。

Poco先发现Document类型,把它的Name打印出:#Document,再打印出它的Value,由于在源码中,其值为空字符串,所以什么也没有。

Poco再发现Comment类型,把它的Name打印出:#Comment,由于Comment的值是可以由用户自定义的,所以存在并显示出“This is a comment”。

Poco再发现Element类型,把它的Name打印出:zhong,由于element的Name是由用户定义的,所以存在,然而,它没有值,只可能有属性。

Poco再发现Text类型,把它的Name打印出:#Text,这个text是element zhong 的,它不可以指定Name,但可以指定Value,这里没有Value,所以没有什么出现。

Poco再发现Attr类型,这说明判断属性的循环进去了,把它的Name打印出:long ,再打印Value 5。由于程序语句执行顺序,这个属性是element guo的

Poco再发现Element类型,把它的Name打印出:guo,没有Value可以打印出。

Poco再发现Text类型,把它的Name打印出:#Text,这个text是element guo的,它不可以指定Name,但可以指定Value,这里Value是“hahah”。

最后,值得注意一下,我发现父子Element元素之间还有一个Text element,比如上面这份数据,在</guo> 和 </zhong>之间就存在这样一个元素,所以在屏幕上最后会打印Name:#Text,而没有值。

可以这样设置:

<zhong>wo
	<guo>shi
		<ren>zhong
		</ren>guo
	</guo>ren
</zhong>
这样,解析后的每个Text元素都有Value了。

还没有涉及更加复杂的XML操作,因为我在项目中对XML数据格式的要求不太复杂,主要集中在节点属性这一块,就这足够了。

以上分析建立在本人没有系统的学习过XML知识的前提下。

谢谢观赏!