写在前面:本文介绍2种MATLAB XML操作的方法:1.MATLAB自带的xmlread,xmlwrite;2.xml_io_tools工具包。推荐大家使用xml_io_tools工具包。您如果急着用的话,可以直接看第二部分。
1. MATLAB自带的xmlread,xmlwrite
1.1 函数和方法简介
xmlread
Read XML document and return Document Object Model node
Syntax: DOMnode= xmlread(filename) % reads the specified XML file and returns a Document Object Model node representing the document
xmlwrite
Write XML Document Object Model node
Syntax: xmlwrite(filename,DOMnode) % writes the Document Object Model (DOM) node DOMnode to the file filename
str = xmlwrite(DOMnode) % serializes the DOM node to a string
可以看到,在MATLAB中,使用xmlread读取XML文件,输出一个表示此XML结构的文档对象模型(Document Object Model,缩写DOM)节点,然后对XML文件的操作都要转化为对DOM节点的操作,最后使用xmlwrite把DOM节点写入到xml文件中。
DOM是表示和处理一个HTML或XML文档的常用方法,它可以以一种独立于平台和语言的方式访问和修改一个文档的内容和结构。关于DOM的资料在网上很多,xmlread的帮助文档里也有涉及。DOM节点的操作方法都在http://download.oracle.com/javase/6/docs/api/org/w3c/dom/package-summary.html,下面列举一些常用的方法。
Document
Element getDocumentElement()
This is a convenience attribute that allows direct access to the child node that is the document element of the document.
String getXmlVersion()
An attribute specifying, as part of the XML declaration, the version number of this document.
Void setXmlVersion(String xmlVersion)
An attribute specifying, as part of the XML declaration, the version number of this document.
Element
NodeList getElementsByTagName(String name)
Returns a NodeList of all descendant Elements with a given tag name, in document order.
Element createElement(String tagName)
Creates an element of the type specified.
Node
String getNodeName()
The name of this node, depending on its type;
String getTextContent()
This attribute returns the text content of this node and its descendants.
Void setTextContent(String textContent)
This attribute returns the text content of this node and its descendants.
Node appendChild(Node newChild)
Adds the node newChild to the end of the list of children of this node.
Node removeChild(Node oldChild)
Removes the child node indicated by oldChild from the list of children, and returns it.
Node replaceChild(Node newChild, Node oldChild)
Replaces the child node oldChild with newChild in the list of children, and returns the oldChild node.
Node cloneNode(boolean deep)
Returns a duplicate of this node, i.e., serves as a generic copy constructor for nodes.
boolean hasChildNodes()
Returns whether this node has any children.
boolean isEqualNode(Node arg)
Tests whether two nodes are equal.
boolean isSameNode(Node other)
Returns whether this node is the same node as the given one.
NodeList
Int getLength()
The number of nodes in the list.
Node item(int index)
Returns the indexth item in the collection.
Attribute
String getAttribute(String name)
Retrieves an attribute value by name.
Void setAttribute(String name, String value)
Adds a new attribute.
Attr createAttribute(String name)
Creates an Attr of the given name.
Void removeAttribute(String name)
Removes an attribute by name.
Attr removeAttributeNode(Attr oldAttr)
Removes the specified attribute node.
Boolean hasAttributes()
Returns whether this node (if it is an element) has any attributes.
这些方法的使用都很简单,基本上从名称就能判断这个方法是干什么的。
1.2 注意事项
下面来看一点注意事项:xmlread对于xml文件的书写格式很敏感。对于下面两种书写格式,会读出不同的结果。
第一种书写格式,暂且叫做常规型,记为regular.xml:
<?xml version="1.0" encoding="utf-8"?>
<Video>
<Title>Assessing the Performance of a Graph-based Clustering Algorithm </Title>
<Author>Pasquale Foggia, University of Naples Federico II </Author>
<Categories>Computer Science,Machine Learning,Clustering</Categories>
<UrlAddress>http://videolectures.net/gbr07_foggia_atp/</UrlAddress>
<Slide Time="0:00" Headline="Assessing the performance of a Graph-based Clustering Algorithm"/>
<Slide Time="0:14" Headline="Outline"/>
</Video>
可以看到,根节点Video有6个子节点,但是读出来却有13个,为什么呢?看看这13个子节点就知道了:空格,Title节点,空格,Author节点,……,空格,Slide节点,空格。原来xmlread认为这种书写格式的各个节点之间的空格,也是节点,所以会读出很多空格。
第二种书写格式,叫紧凑型吧,记为compact.xml:
<?xml version="1.0" encoding="utf-8"?><Video><Title>Assessing the Performance of a Graph-based Clustering Algorithm </Title><Author>Pasquale Foggia, University of Naples Federico II </Author><Categories>Computer Science,Machine Learning,Clustering</Categories><UrlAddress>http://videolectures.net/gbr07_foggia_atp/</UrlAddress><Slide Time="0:00" Headline="Assessing the performance of a Graph-based Clustering Algorithm"/><Slide Time="0:14" Headline="Outline"/></Video>
紧凑型的书写格式,读出来根节点Video有6个子节点:Title节点,Author节点,……,Slide节点。
基于这一注意事项,另外一些看似很好用很酷的方法,如getChildNodes()、getParentNode()、getFirstChild()、getLastChild()、getNextSibling()、getPreviousSibling(),用起来要十分小心了。比如你读的是上面的regular.xml,你想拿到Video的第一个子节点Title,你使用getFirstChild()方法,返回是空格而不是你想要的。当然紧凑型的xml文件并不存在这样的问题。
1.3 例子
最后来看一个简单的例子吧!
首先假设输入文件是:regular.xml。
clear
xDoc=xmlread('regular.xml');%读取XML文件
xRoot=xDoc.getDocumentElement();%获取根节点,即Video
% 获取节点
Slides= xRoot.getElementsByTagName('Slide');% 获取Slide节点集合
Num_Slides=Slides.getLength();%查看Slide节点的个数,返回2
Slide1=Slides.item(0);%从Slide节点集合获取第一个Slide节点,注意集合的索引已从0开始的
% 对于Title的这样的单一节点,同样使用getElementsByTagName方法获取:Title= xRoot.getElementsByTagName('Title').item(0);
% 获取属性值,设置属性值,添加属性值
Slide1Time=char(Slide1.getAttribute('Time'));%获取Slide1的Time属性,注意getTextContent()返回的是java.lang.String类型,使用char函数将它转化为MATLAB中的字符串类型
Slide1.setAttribute('Time','0:05');%修改Slide1的Time属性
Slide1.setAttribute('Date','2011/11/14');%为Slide1添加Date属性,并设置为'2011/11/14'
% 获取文本内容,设置文本内容
Slide1Content=char(Slide1.getTextContent());%获取Slide1的文本内容
Slide1.setTextContent('Good morning!');%设置Slide1的文本内容
% 新建节点,插入节点
newSlide=xDoc.createElement('Slide');%新建newSlide节点
newSlide.setAttribute('Time','2:00');%设置Time属性
newSlide.setAttribute('Headline','Thank you!');%设置Headline属性
newSlide.setTextContent('That''s all!');%设置文本内容
xRoot.appendChild(newSlide);%将newSlide插入xRoot的末尾
xmlwrite('regular_output.xml',xDoc);%保存结果到example_output.xml
输出文件regular_output.xml的内容如下:
<?xml version="1.0" encoding="utf-8"?>
<Video>
<Title>Assessing the Performance of a Graph-based Clustering Algorithm </Title>
<Author>Pasquale Foggia, University of Naples Federico II </Author>
<Categories>Computer Science,Machine Learning,Clustering</Categories>
<UrlAddress>http://videolectures.net/gbr07_foggia_atp/</UrlAddress>
<Slide Date="2011/11/14" Headline="Assessing the performance of a Graph-based Clustering Algorithm" Time="0:05">Good morning!</Slide>
<Slide Headline="Outline" Time="0:14"/>
<Slide Headline="Thank you!" Time="2:00">That's all!</Slide>
</Video>
如果输入文件是:compact.xml, 那么输出文件的内容是:
<?xml version="1.0" encoding="utf-8"?>
<Video>
<Title>Assessing the Performance of a Graph-based Clustering Algorithm </Title>
<Author>Pasquale Foggia, University of Naples Federico II </Author>
<Categories>Computer Science,Machine Learning,Clustering</Categories>
<UrlAddress>http://videolectures.net/gbr07_foggia_atp/</UrlAddress>
<Slide Date="2011/11/14" Headline="Assessing the performance of a Graph-based Clustering Algorithm" Time="0:05">Good morning!</Slide>
<Slide Headline="Outline" Time="0:14"/>
<Slide Headline="Thank you!" Time="2:00">That's all!</Slide>
</Video>
小结:MATLAB对于XML文件的这种操作方式,方法很多很全面,但是看起来有点繁琐,不易掌握。
2. xml_io_tools
FUNCTIONS(part):
xml_read read XML file into Matlab structure
xml_write write Matlab structure into XML files
可以看到,这个工具包是将XML文件读为MATLAB结构体,拿上面的regular.xml来说。
Video = xml_read('regular.xml');
Video就是一个结构体:
可以看到,Video的每个节点都被读为它的一个域。对于没有属性的节点,如Title节点,Video.Title是字符串,其值为XML文件中Title节点的文本内容。对于有属性的节点,如第一个Slide节点,Video.Slide(1)是一个结构体:
Video.Slide(1).Content是XML文件中第一个Slide节点的文本内容。Video.Slide(1).ATTRIBUTE是XML文件中第一个Slide节点的属性,它又是一个结构体:
这样一来,就可以了解xml_read是如何将XML文件读为MATLAB结构体的了!而且xml_read对于xml文件的书写格式不敏感,就是说使用xml_read读取regular.xml和compact.xml,结果是一样的。
既然获得了结构体,那么对于XML的一些操作,就很容易了。
clear
Video = xml_read('regular.xml');%读取XML
TitleContent=Video.Title;%获取Title节点的文本内容
Slide1Content=Video.Slide(1).CONTENT;%获取第一个Slide节点的文本内容
Slide1Time=Video.Slide(1).ATTRIBUTE.Time;%获取第一个Slide节点的Time属性
Video.Slide(1).CONTENT='Good morning!';%修改第一个Slide节点的文本内容
Video.Slide(1).ATTRIBUTE.Time='0.05';%修改第一个Slide节点的Time属性
Video.Slide(1).ATTRIBUTE.Date='2011/11/14';%为第一个Slide节点添加Date属性,并设置为'2011/11/14'
% 新建节点,插入节点
newSlide=struct;%新建newSlide节点
newSlide.CONTENT='That''s all!';%设置文本内容
newSlide.ATTRIBUTE.Time='2:00';%设置Time属性
newSlide.ATTRIBUTE.Headline='Thank you!';%设置Headline属性
Video.Slide(end+1)=newSlide;%将newSlide插入Video的末尾
wPref.StructItem = false;%设置:重复节点写入时,不使用'item'
xml_write('regular_output.xml',Video,'Video',wPref);%保存XML
输出文件的内容可想而知,这里就不再贴出来了。
小结:可以看出,xml_io_tools工具包对于XML文件的操作,相比于MATLAB来说比较简单,容易操作。
推荐大家使用xml_io_tools工具包,下载地址:http://www.mathworks.com/matlabcentral/fileexchange/12907-xmliotools