PHP读取XML文档内容的方法

我们要读取一个结构如下的XML文档的内容:

<row>
<field name="id">1</field>
<field name="code">110000</field>
<field name="name">北京</field>
</row>
<row>
<field name="id">2</field>
<field name="code">120000</field>
<field name="name">天津</field>
</row>
<row>
<field name="id">3</field>
<field name="code">130000</field>
<field name="name">河北</field>
</row>

读取的方法很简单:

//首先要建一个DOMDocument对象
$doc = new DOMDocument();
//加载XML文件
$doc->load('xml/province.xml');
//获取所有的row标签
$rows = $doc->getElementsByTagName("row");
$data = array();
//遍历所有的row标签
foreach ($rows as $row) {
	$field = $row->getElementsByTagName("field");
	//item代表field标签的顺序,nodeValue是这个节点的值
	$id = $field->item(0)->nodeValue;
	$code = $field->item(1)->nodeValue;
	$name = $field->item(2)->nodeValue;
	$data = array(
		'id' => $id,
		'code' => $code,
		'name' => $name
	);
}

以下是DOMDocument的一些属性和方法:

属性:
Attributes 存储节点的属性列表(只读)
childNodes
存储节点的子节点列表(只读)
dataType 返回此节点的数据类型
Definition
以DTD或XML模式给出的节点的定义(只读)
Doctype 指定文档类型节点(只读)
documentElement
返回文档的根元素(可读写)
firstChild 返回当前节点的第一个子节点(只读)
Implementation
返回XMLDOMImplementation对象
lastChild 返回当前节点最后一个子节点(只读)

nextSibling 返回当前节点的下一个兄弟节点(只读)
nodeName 返回节点的名字(只读)

nodeType 返回节点的类型(只读)
nodeTypedValue 存储节点值(可读写)

nodeValue 返回节点的文本(可读写)
ownerDocument 返回包含此节点的根文档(只读)

parentNode 返回父节点(只读)
Parsed 返回此节点及其子节点是否已经被解析(只读)

Prefix 返回名称空间前缀(只读)
preserveWhiteSpace 指定是否保留空白(可读写)

previousSibling 返回此节点的前一个兄弟节点(只读)
Text 返回此节点及其后代的文本内容(可读写)

url 返回最近载入的XML文档的URL(只读)
Xml
返回节点及其后代的XML表示(只读)

方法:
appendChild
为当前节点添加一个新的子节点,放在最后的子节点后
cloneNode 返回当前节点的拷贝
createAttribute
创建新的属性
createCDATASection 创建包括给定数据的CDATA段
createComment
创建一个注释节点
createDocumentFragment 创建DocumentFragment对象

createElement 创建一个元素节点
createEntityReference
创建EntityReference对象
createNode 创建给定类型,名字和命名空间的节点

createPorcessingInstruction 创建操作指令节点
createTextNode
创建包括给定数据的文本节点
getElementsByTagName 返回指定名字的元素集合
hasChildNodes
返回当前节点是否有子节点
insertBefore 在指定节点前插入子节点
Load 导入指定位置的XML文档

loadXML 导入指定字符串的XML文档
removeChild 从子结点列表中删除指定的子节点

replaceChild 从子节点列表中替换指定的子节点
Save 把XML文件存到指定节点

selectNodes 对节点进行指定的匹配,并返回匹配节点列表
selectSingleNode
对节点进行指定的匹配,并返回第一个匹配节点
transformNode 使用指定的样式表对节点及其后代进行转换

 

Tonitech版权所有 | 转载请注明出处: http://www.tonitech.com/?p=1482

C++处理XML文件

选择一:市面上的XML lib还是有几个的,最有名的当然是libXML。

选择二:MS的MSXML,可以查看下MSDN文档。

选择三:使用开源类CMarkup,今天主要讲这个。

网上有Cmarkup的源代码,你可以下载后在里面include你的头文件,然后创建一个Cmarkup的对象,然后就可以调用里面的成员函数对你所希望操作的XML文件进行操作了。

下面是CMarkup的类成员函数使用方法。这些函数的设计都是基于源EDOM的。

创建一个XML文档

对于创建一个XML文档,需要实例化一个CMarkup对象,并调用AddElem创建根元素。.在这个位置,如果你调用AddElem(“ORDER”) ,你的文档会简单的装一个空ORDER元素. 然后调用AddChildElem 在根元素的下面创建元素 (例如:“进入”根元素内部,层次表示).下面的示例代码创建一个XML文档并返回它(的内容)到一个字符串中。

CMarkup xml;
xml.AddElem( "ORDER" );
xml.AddChildElem( "ITEM" );
xml.IntoElem();
xml.AddChildElem( "SN", "132487A-J" );
xml.AddChildElem( "NAME", "crank casing" );
xml.AddChildElem( "QTY", "1" );
CString csXML = xml.GetDoc();

这些代码产生了下面的XML,这个根结点是ORDER元素;注意它的开始标签 在开头,结束标签在结尾。当一个元素是在一个父下面(深入或被包含),这个父元素的开始标签要在它之前,结束标签要在它之后。ORDER元素包含一个ITEM元素,而ITEM元素包含了三个字子元素:SN、NAME和QTY;

132487A-J

crank casing

1

如例子中所显示的,你也能够在一个子元素下创建新元素,这需要调用IntoElem 移动你的当前主位置到当前子元素位置,然后你就可以在这下面增加一个子元素了。CMarkup在索引中保持了一个当前位置指针,以保证你的源码更加短和更简单,当导航文件时,相同的逻辑位置也会被使用。

导航XML文档

上面的例子所创建的XML字符串,用SetDoc方法加入到CMarkup对象中能够被解析,你也可以引导它正确的进入被创建的同一个CMarkup对象中,如果你要设置当前位置到文档的开始时,需要调用ResetPos.

在下面的例子中,从csXML字符串生成CMarkup对象后,我们循环ORDER元素下的所有ITEM元素,并得到每个项目的序号和数量。

CMarkup xml;
xml.SetDoc( csXML );
while ( xml.FindChildElem("ITEM") )
{
    xml.IntoElem();
    xml.FindChildElem( "SN" );
    CString csSN = xml.GetChildData();
    xml.FindChildElem( "QTY" );
    int nQty = atoi( xml.GetChildData() );
    xml.OutOfElem();
}

对于我们发现的每个元素,在查询它了子元素之前要调用IntoElem,查询完之后再调用OutOfElem ,当你习惯于这种导航类型时,你将知道,检查你的循环时,要确定每个IntoElem 调用都有一个与之对应的OutOfElem 调用 。

增加元素和属性

上面创建文档的例子中仅创建了一个ITEM元素,现在这个例子是创建多个项目,从前一个内容加裁后,再增加数据源,加上SHIPMENT信息元素中有一个属性,这段代码也演示了你能调用调用IntoElem和AddElem来代替AddChildElem,函数调用。虽然这意味着更多的调用,但许多人认为这样更直观。

CMarkup xml;
xml.AddElem( "ORDER" );
xml.IntoElem(); // inside ORDER
for ( int nItem=0; nItem
{
    xml.AddElem( "ITEM" );
    xml.IntoElem(); // inside ITEM
    xml.AddElem( "SN", aItems[nItem].csSN );
    xml.AddElem( "NAME", aItems[nItem].csName );
    xml.AddElem( "QTY", aItems[nItem].nQty );
    xml.OutOfElem(); // back out to ITEM level
}
xml.AddElem( "SHIPMENT" );
xml.IntoElem(); // inside SHIPMENT
xml.AddElem( "POC" );
xml.SetAttrib( "type", csPOCType );
xml.IntoElem(); // inside POC
xml.AddElem( "NAME", csPOCName );
xml.AddElem( "TEL", csPOCTel );

这段代码产生了下面的XML,根元素ORDER包含两个ITEM元素和一个SHIPMENT元素,ITEM元素全都包含SN、NAME、和QTY元素,SHIPMENT元素包含一个带有属性类型的POC元素,和NAME及TEL子元素。

132487A-J

crank casing

1

4238764-A

bearing

15

John Smith

555-1234

查找元素

FindElem 和 FindChildElem方法用于到下一个兄弟元素。如果可选的标签名被指定,那么它们将到下一个与标签名相匹配的元素,被发现的元素是当前元素,并且下次调用Find将会到当前位置后的下一个兄弟或下一个匹配兄弟。

当你无法判断元素的索引时,在调用两个Find方法之间,一定要复位当前位置。看上面的例子中ITEM元素,如果是别的人创建的XML文件,你不能确定SN元素在QTY元素之前,那么在查找QTY元素之前就要调用ResetChildPos();

对于用一个特定的序号去查找元素,你需要完全循环ITEM元素,并比较SN元素的数据和你正在搜索的序号。这个例子不同于先前导航的例子,它调用IntoElem 进入到ORDER元素,并且用FindElem(“ITEM”)替换FindChildElem(“ITEM”);其实两种方式都挺好。需要注意的是,在Find方法中指定ITEM元素的标签名,我们会忽略所有其它的兄弟元素,例如SHIPMENT元素。

CMarkup xml;
xml.SetDoc( csXML );
xml.FindElem(); // ORDER element is root
xml.IntoElem(); // inside ORDER
while ( xml.FindElem("ITEM") )
{
    xml.FindChildElem( "SN" );
    if ( xml.GetChildData() == csFindSN )
        break; // found
}

编码

ASCII编码引用了我们所依靠的字符码128以下的字符,如用英语编程。如果你只使用ASCII码,很方便,UTF-8编程与你拉公共ASCII集相同。

如果你所使用的字符集不在Unicode编码集(UTF-8,UTF-16,UCS-2)中,那么出于交互性以及在IE中很好的显示,你真的需要在XML声明中进行描述。像ISO-8859-1(西欧)字符集指定字符值在一个比特且在128到255之间。以便每个字符仍然使用一个比特。Windows双字节字符集像GB2312,Shift_JIS和EUC-KR,每个字符都是用一个或两个字节,对于这些Windows字符集,在你的预处理中需要定义_MBCS ,并要确定用户的操作系统设置到合适的编码页。

关于用一个XML描述的XML文档前缀,像,需要通过用SetDoc或Cmarkup的构造函数来传递。在结尾要包括回车符,这样根结点会显示在下一行。

xml.SetDoc( "/r/n" );
xml.AddElem( "island", "Curaçao" );

Tonitech版权所有 | 转载请注明出处: http://www.tonitech.com/?p=948