VTD-XML基本原理介绍

VTD-XML是一种无提取的XML解析方法,它较好的解决了DOM占用内存过大的缺点,并且还提供了快速的解析与遍历、对XPath的支持和增量更新等特性。VTD-XML是一个开源项目,目前有Java、C两种平台支持。

为了实现non-extractive(非提取)这个目的,它将原XML文件原封不动的以二进制的方式读进内存,连解码都不做,然后在这个二进制byte数组上解析每个 element的位置并把一些信息记录下来,这种记录就被成为VTD(Virtual Token Descriptor,虚拟令牌描述符)。

之后的遍历操作便在这些保存下来的记录上进行,如果需要提取XML内容就利用记录中的位置等 信息在原始byte数组上进行解码并返回字符串。
VTD(Virtual Token Descriptor,虚拟令牌描述符)结构
VTD是一个64bits定长的数值类型,记录了每个元素的起始位置(offset),长度(length),深度(depth)以及令牌(元素标签)的类型(type)等信息。

如下图,表示了每个元素的位置及类型信息,对Xml的所有操作都是基于这个数据结构。


VTD-XML基本原理介绍_第1张图片
 下图表示了VTD目前所支持的所有元素的类型(12种):
VTD-XML基本原理介绍_第2张图片
 
查询与更新:

如果需要提取XML内容,就查找VTD数组,利用VTD记录中的位置等信息在原始比特数组上进行解码并返回字符串。
而且VTD-XML还可以高效的实现增量更新,例如,如果想在一个大型XML文档中找出一个节点元素并删除它,那么只需要找到这个元素的VTD,将这个VTD从VTD数组中删除,然后再利用所有的VTD写出到另一个二进制数组中就可以了,这就是所谓增量更新。这个过程实际上就是一个二进制数组的拷贝过程,其效率是非常高的。

 

下图是三种主要的XML解析的相关功能及性能比较:
VTD-XML基本原理介绍_第3张图片
 

第三部分:应用实例

 

VTD-XML解析xml通常经过以下几步:
    1.以一个byte数组开始(存放xml);
    2.利用VTDGen进行解析;
    3. 利用VTDNav进行导航定位;
    4. 节点遍历使用Autopilot;
    5. 利用Xpath进行节点选择
    6. 增量更新使用XMLModifier

 

下面的代码主要功能:首先根据Xpath选择某些属性partNum='872-AA' 的item元素并用someting元素替换;替换价格小于40的元素文本为200.

/* In this java program, we demonstrate how to use XMLModifier to incrementally 
 * update an simple XML purchase order. 
 * a particular name space. We also are going  
 * to use VTDGen's parseFile to simplify programming. 
 */  
import java.io.File;  
import java.io.FileOutputStream;  
  
import com.ximpleware.AutoPilot;  
import com.ximpleware.ModifyException;  
import com.ximpleware.NavException;  
import com.ximpleware.VTDGen;  
import com.ximpleware.VTDNav;  
import com.ximpleware.XMLModifier;  
  
public class update {  
  
  public static void main(String argv[]){  
     try {  
    // open a file and read the content into a byte array  
    VTDGen vg = new VTDGen();  
    String path = update.class.getResource("").getPath();  
    System.out.println(path);  
      
    if (vg.parseFile(path + "oldpo.xml", true)){  
        VTDNav vn = vg.getNav();  
        File fo = new File("f:/newpo.xml");  
        FileOutputStream fos = new FileOutputStream(fo);  
        AutoPilot ap = new AutoPilot(vn);  
        XMLModifier xm = new XMLModifier(vn);  
        ap.selectXPath("/purchaseOrder/items/item[@partNum='872-AA']");  
        int i = -1;  
        while((i=ap.evalXPath())!=-1){  
            xm.remove();  
            xm.insertBeforeElement("<something/>\n");   
        }  
        ap.selectXPath("/purchaseOrder/items/item/USPrice[.<40]/text()");  
        while((i=ap.evalXPath())!=-1){  
            xm.updateToken(i,"200");  
        }  
        xm.output(fos);  
        fos.close();  
    }  
     }  
     catch (NavException e){  
         System.out.println(" Exception during navigation "+e);  
     }  
     catch (ModifyException e){  
         System.out.println(" Modify exception occurred "+e);  
     }  
     catch (Exception e){  
     }  
  }  

 修改前的Xml文件:

 

<?xml version="1.0" encoding="UTF-8"?>
<purchaseOrder orderDate="1999-10-20">
    <comment>Hurry, my lawn is going wild!</comment>
    <items>
        <item partNum="872-AA">
            <productName>Lawnmower</productName>
      <quantity><![CDATA[1]]></quantity>
            <USPrice>148.95</USPrice>
            <comment>Confirm this is electric</comment>
        </item>
        <item partNum="926-AA">
            <productName>Baby Monitor</productName>
            <quantity>1</quantity>
            <USPrice>39.98</USPrice>
            <shipDate>1999-05-21</shipDate>
        </item>
    </items>
</purchaseOrder>

 

 

修改后的Xml文件,红色字体为修改后的:

<?xml version="1.0"?>
<purchaseOrder orderDate="1999-10-20">
    <comment>Hurry, my lawn is going wild!</comment>
    <items>
        <something/>
       <item partNum="926-AA">
            <productName>Baby Monitor</productName>
            <quantity>1</quantity>
            <USPrice>200</USPrice>
            <shipDate>1999-05-21</shipDate>
        </item>
    </items>
</purchaseOrder>

官网地址:http://vtd-xml.sourceforge.net/ 

你可能感兴趣的:(xml)