XML解析之SAX方式

article/2025/9/27 22:19:24

XML文件解析方式之一是SAX方式,SAX解析方式会逐行地去扫描XML文档,当遇到标签时会触发解析处理器,采用事件处理的方式解析XML (Simple API for XML) 。SAX是一个用于处理XML事件驱动的“推”模型,虽然不是官方标准,但它是 XML 社区事实上的标准,几乎所有的 XML 解析器都支持它。

SAX解析不像DOM那样建立一个完整的文档树,而是在读取文档时激活一系列事件,这些事件被推给事件处理器,然后由事件处理器提供对文档内容的访问。常见的事件处理器有三种基本类型:

  • 用于访问XML DTD内容的DTDHandler;
  • 用于低级访问解析错误的ErrorHandler;
  • 用于访问文档内容的ContentHandler,这也是最普遍使用的事件处理器。

  解析器读取输入文档并在处理文档时将每个事件推给文档处理器(MyContentHandler)。

   与DOM相比,SAX解析器能提供更好的性能优势,它提供对XML文档内容的有效低级访问。SAX模型最大的优点是内存消耗小,因为整个文档无需一次加载到内存中,这使SAX解析器可以解析大于系统内存的文档。另外,你无需像在DOM中那样为所有节点创建对象。最后,SAX“推”模型可用于广播环境,能够同时注册多个ContentHandler,并行接收事件,而不是在一个管道中一个接一个地进行处理。

  SAX的缺点是必须实现多个事件处理程序以便能够处理所有到来的事件,同时你还必须在应用程序代码中维护这个事件状态,因为SAX解析器不能交流元信息,如DOM的父/子支持,所以你必须跟踪解析器处在文档层次的哪个位置。如此一来,你的文档越复杂,你的应用逻辑就越复杂。虽然没有必要一次将整个文档加载到内存中,但SAX解析器仍然需要解析整个文档,这点和DOM一样。也许SAX面临的最大问题是它没有内置如XPath所提供的那些导航支持。再加上它的单遍解析,使它不能支持随机访问。这一限制也表现在名字空间上: 对有继承名字空间的元素不做注解。这些限制使SAX很少被用于操作或修改文档。

  那些只需要单遍读取内容的应用程序可以从SAX解析中大大受益。很多B2B和EAI应用程序将XML用做封装格式,接收端用这种格式简单地接收所有数据。这就是SAX明显优于DOM的地方:因高效而获得高吞吐率。在SAX 2.0 中有一个内置的过滤机制,可以很轻松地输出一个文档子集或进行简单的文档转换。

 一、SAX解析方式的步骤

SAX解析可分四个步骤进行:

  1. 得到xml文件对应的资源,可以是xml的输入流,文件或uri
  2. 得到SAX解析工厂(SAXParserFactory)
  3. 由解析工厂生产一个SAX解析器(SAXParser)
  4. 传入输入流和handler给解析器,调用parse()解析

二、SAX的常用接口介绍

1、ContentHandler接口

 该接口封装了一些对事件处理的方法,当XML解析器开始解析XML输入文档时,它会遇到某些特殊的事件,比如文档的开头和结束、元素开头和结束、以及元素中的字符数据等事件。当遇到这些事件时,XML解析器会调用ContentHandler接口中相应的方法来响应该事件。ContentHandler接口的方法有以下几种:

  void startDocument()void endDocument()void startElement(String uri, String localName, String qName, Attributes atts)void endElement(String uri, String localName, String qName)void characters(char[ ] ch, int start, int length)

2、ErrorHandler接口

  ErrorHandler接口是SAX错误处理程序的基本接口。如果SAX应用程序需要实现自定义的错误处理,则它必须实现此接口,然后解析器将通过此接口报告所有的错误和警告。该接口的方法如下:

  void error(SAXParseException exception)void fatalError(SAXParseException exception)void warning(SAXParseException exception)

3、DTDHandler接口

DTDHandler用于接收基本的DTD相关事件的通知,仅包括DTD事件的注释和未解析的实体声明部分。SAX解析器可按任何顺序报告这些事件,而不管声明注释和未解析实体时所采用的顺序;但是,必须在文档处理程序的startDocument()事件之后,在第一个startElement()事件之前报告所有的DTD事件。DTDHandler接口包括以下两个方法:

  void startDocumevoid notationDecl(String name, String publicId, String systemId) nt()void unparsedEntityDecl(String name, String publicId, String systemId, String notationName)

4、EntityResolver接口

EntityResolver接口是用于解析实体的基本接口,该接口只有一个方法,如下:

  public InputSource resolveEntity(String publicId, String systemId)

  解析器将在打开任何外部实体前调用此方法。此类实体包括在DTD内引用的外部DTD子集和外部参数实体和在文档元素内引用的外部通用实体等。如果SAX应用程序需要实现自定义处理外部实体,则必须实现此接口。

三、Xerces C++ SAX解析XML文档

1、编译xerces

https://blog.csdn.net/t18438605018/article/details/117478843

2、在工程中使用xerces

  1. 编译xerces成功后,在生成目录会生成xerces-c_3_1D.dll,xerces-c_3_1D.lib。(如果是release模式,就不会有后面的D)
  2. 新建VS工程,添加C++/include目录和link/xerces-c_3_1D.lib,拷贝xerces-c_3_1D.dll到工程生成目录
  3. 添加测试程序
// MySAXHandler.h
#pragma once  
#include <xercesc/sax2/DefaultHandler.hpp>  
#include <xercesc/sax2/Attributes.hpp>XERCES_CPP_NAMESPACE_USEclass MySAX2Handler : public DefaultHandler
{
public:MySAX2Handler();~MySAX2Handler();
public:void startElement(const   XMLCh* const    uri,const   XMLCh* const    localname,const   XMLCh* const    qname,const   Attributes&     attrs);void characters(const   XMLCh* const    chars,const XMLSize_t       length);void endElement(const XMLCh* const uri,const XMLCh* const localname,const XMLCh* const qname);void fatalError(const SAXParseException&);
};

// MySAXHandler.cpp#include "MySAXHandler.h"
#include <iostream>MySAX2Handler::MySAX2Handler()
{
}MySAX2Handler::~MySAX2Handler()
{
}void MySAX2Handler::startElement(const   XMLCh* const    uri,const   XMLCh* const    localname,const   XMLCh* const    qname,const   Attributes&     attrs)
{char* message = XMLString::transcode(qname);std::cout << "start element: " << message << std::endl;XMLString::release(&message);
}void MySAX2Handler::fatalError(const SAXParseException& exception)
{char* message = XMLString::transcode(exception.getMessage());std::cout << "Fatal Error: " << message<< " at line: " << exception.getLineNumber()<< std::endl;XMLString::release(&message);
}void MySAX2Handler::characters(const XMLCh* const chars, const XMLSize_t length)
{
}void MySAX2Handler::endElement(const XMLCh* const uri,const XMLCh* const localname,const XMLCh* const qname) 
{char* message = XMLString::transcode(qname);std::cout << "end element: " << message << std::endl;XMLString::release(&message);
}
// main.cpp
#include <xercesc/util/PlatformUtils.hpp>  
#include <xercesc/sax2/SAX2XMLReader.hpp>  
#include <xercesc/sax2/DefaultHandler.hpp>  
#include <xercesc/sax2/XMLReaderFactory.hpp>  
#include <xercesc/util/XMLString.hpp>  
#include <iostream>#include "MySAXHandler.h"int main(int argc, char*  args[])
{try {XMLPlatformUtils::Initialize();}catch (const XMLException& toCatch){char* message = XMLString::transcode(toCatch.getMessage());std::cout << "Error during initialization! :\n";std::cout << "Exception message is: \n"<< message << "\n";XMLString::release(&message);return 1;}const char* xmlFile = "./data/personal.xml";SAX2XMLReader* parser = XMLReaderFactory::createXMLReader();parser->setFeature(XMLUni::fgSAX2CoreValidation, true);parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);   // optionalparser->setFeature(XMLUni::fgXercesDynamic, false);parser->setFeature(XMLUni::fgXercesSchema, true);parser->setFeature(XMLUni::fgXercesSchemaFullChecking, true);MySAX2Handler* defaultHandler = new MySAX2Handler();parser->setContentHandler(defaultHandler);parser->setErrorHandler(defaultHandler);parser->setEntityResolver(defaultHandler);try{parser->parse(xmlFile);}catch (const XMLException& toCatch){char* message = XMLString::transcode(toCatch.getMessage());std::cout << "Exception message is: \n"<< message << "\n";XMLString::release(&message);return -1;}catch (const SAXParseException& toCatch){char* message = XMLString::transcode(toCatch.getMessage());std::cout << "Exception message is: \n"<< message << "\n";XMLString::release(&message);return -1;}catch (...) {std::cout << "Unexpected Exception \n";return -1;}//defaultHandler->OutputPsList();delete parser;delete defaultHandler;XMLPlatformUtils::Terminate();system("PAUSE");return 0;}

运行结果:

 


http://chatgpt.dhexx.cn/article/ZN0RAlp0.shtml

相关文章

实现XML解析的几种技术

XML在各种开发中都广泛应用&#xff0c;Android也不例外。作为承载数据的一个重要角色&#xff0c;如何读写XML成为Android开发中一项重要的技能。今天就由我向大家介绍一下在Android平台下几种常见的XML解析和创建的方法。 在Android中&#xff0c;常见的XML解析器分别为SAX解…

MATLAB中的均值与方差求法(mean,var,std函数使用)

目录 均值-mean()函数的用法方差var函数std函数 均值-mean()函数的用法 对于矩阵A&#xff1a; &#xff08;1&#xff09;mean(A,1)为对矩阵A的列求均值 &#xff08;2&#xff09;mean(A,2)为对矩阵A的行求均值 &#xff08;3&#xff09;mean(A)当传入的参数只有矩阵时&a…

matlab怎么方差函数,密度函数已知,怎么用matlab求其数学期望和方差?

在没有先验知识的情况下是不可能的&#xff0c;在你已知它可能是哪种分布(或者哪些种分布之一)的情况下可以求出分布的参数www.mh456.com防采集。 因为你的是密度函2113数&#xff0c;所以不会5261是离散型随机变量&#xff0c;如果你有4102概率密度函数的表达式的话&#xff0…

matlab怎么算方差和标准差,matlab怎么求矩阵的均值和标准差 看完你就知道了

有时候我们在使用matlab编程计算的时候&#xff0c;想求矩阵的均值和方差&#xff0c;怎么求呢&#xff0c;下面来分享一下方法 工具/材料 matlab 求矩阵的均值和标准差方法 matlab求矩阵均值方法 01 第一步打开matlab命令行窗口&#xff0c;新建一个a[1 2 3;4 5 6;7 8 9]矩阵&…

剩余方差matlab,用matlab的var函数求方差

什么是方差和标准差&#xff1f; 方差(variance) 和标准差(standard variance) 方差&#xff1a;表示一组离散数据偏离平均值的程度。 公式&#xff1a; 方差公式 方差的算术平方根称为该随机变量的标准差。 在Matlab中&#xff0c;方差用var函数求&#xff0c;标准差用std函数…

matlab里方差分析的盒子图怎么看,Matlab方差分析

Matlab 方差分析(T检验) 在工农业生产和科学研究中,经常遇到这样的问题:影响产品产量、质量的因素很多,我们需要了解在这众多的因素中,哪些因素对影响产品产量、质量有显著影响.为此,要先做试验,然后对测试的结果进行分析.方差分析就是分析测试结果的一种方法.在方差分析中,把在…

20171205_Matlab求方差,均值,均方差,协方差的函数

1、 均值 数学定义&#xff1a; Matlab函数&#xff1a;mean >>X[1,2,3] >>mean(X)2 如果X是一个矩阵&#xff0c;则其均值是一个向量组。mean(X,1)为列向量的均值&#xff0c;mean(X,2)为行向量的均值。 >>X[12 3 45 6] >>mean(X,1)[2.5,3.5, 4.5] &g…

方差分析MATLAB实现

单因素方差分析的MATLAB实现 单因素均衡数据的实现 单因素非均衡数据方差分析 p192 8.22 X[85,80,90,88,87,94,56,62,55,48,92,99,95,91,75,72,81];group[ones(1,3),2*ones(1,4),3*ones(1,2),4*ones(1,2),5*ones(1,4),6*ones(1,3)];anova1(X,group); 从箱线图可以看到第2个第五…

matlab算方差std,MATLAB 方差函数 var std

1、均值 数学定义: Matlab函数:mean >>X=[1,2,3] >>mean(X)=2 如果X是一个矩阵,则其均值是一个向量组。mean(X,1)为列向量的均值,mean(X,2)为行向量的均值。 >>X=[1 2 3 4 5 6] >>mean(X,1)=[2.5, 3.5, 4.5] >>mean(X,2)=[2 5] 若要求整个矩…

matlab 方差,方差分解——matlab 代码

封面图片源自网络: 接着前面两期分析,今天介绍期限结构和收益率的方差分解代码: function var_plot= var_term( Phi_DRAW,OMIGA_ff_DRAW,HH) %%%% HH means the step length for forecast %%%%%%%%%% %%%%%% get the forecast variance decomposition %%%%%%% %%% SIGMA_u=P…

matlab u怎么求均方差,Matlab求方差,均值,均方差,協方差的函數

1、均值 數學定義&#xff1a; Matlab函數&#xff1a;mean >>X[1,2,3] >>mean(X)2 如果X是一個矩陣&#xff0c;則其均值是一個向量組。mean(X,1)為列向量的均值&#xff0c;mean(X,2)為行向量的均值。 >>X[1 2 3 4 5 6] >>mean(X,1)[2.5, 3.5, 4.5]…

Matlab系列教程_数值计算_求方差和标准差

首先&#xff0c;什么是方差和标准差&#xff1f; 方差&#xff0c;是在概率论和统计方差衡量随机变量或一组数据时离散程度的度量&#xff0c;统计中的方差&#xff08;样本方差&#xff09;是每个样本值与全体样本值的平均数之差的平方值的平均数。在许多实际问题中&#xff…

MATLAB中均值、方差、均方差的计算方法

1、 均值 数学定义&#xff1a; &#xff08;自己搜一下&#xff09; Matlab函数&#xff1a;mean >>X[1,2,3] >>mean(X)2 如果X是一个矩阵&#xff0c;则其均值是一个向量组。mean(X,1)为列向量的均值&#xff0c;mean(X,2)为行向量的均值。 >>X[1 2 3 4 5 …

利用MATLAB求均值、方差和标准差

1、 均值 数学定义&#xff1a; Matlab函数&#xff1a;mean 如果X是一个矩阵&#xff0c;则其均值是一个向量组。mean(X,1)为列向量的均值&#xff0c;mean(X,2)为行向量的均值。若要求整个矩阵的均值&#xff0c;则为mean(mean(X))或者mean2(X)。 2、 方差 数学定义&…

matlab 方差计算

代码如下&#xff1a; I imread(); dark_Idouble(I)/255; avgmean2(dark_I); %求图像均值 [m,n]size(dark_I); s0; for x1:mfor y1:nss(dark_I(x,y)-avg)^2; %求得所有像素与均值的平方和。end end%求图像的方差 a1var(dark_I(:)); %第一种方法&#xff1a;利用函数var求得…

环形队列的实现

首先我们先来了解一下队列是什么&#xff1f; 队列&#xff1a;数据先入先出&#xff0c;后进后出&#xff08;与栈刚好相反&#xff09;&#xff0c;主要通过数组实现。需要通过两个指针来创建对应的队列&#xff1b;一个指针为前缀pre&#xff0c;一个指针为后缀rear。pre指…

环形队列(Python代码实现)

环形队列是是在普通队列上进行的变化&#xff0c;本质和普通单向队列相同&#xff0c;都是队尾进队&#xff0c;队首出队。环形队列与普通队列的区别在于它能够循环利用空间&#xff0c;元素从队首出队后释放的空间能够被重复利用。 主要特点&#xff1a; 当队尾指针front M…

队列和环形队列

1、队列 1) 队列是一个有序列表&#xff0c;可以用数组或是链表来实现。 2) 遵循先入先出的原则。即&#xff1a;先存入队列的数据&#xff0c;要先取出。后存入的要后取出。 实例&#xff1a; 声明&#xff1a; MaxSize&#xff1a;队列最大的长度 rear&#xff1a;尾指针&…

数据结构与基础算法-环形队列

一、什么是环形队列。 其实在内存上并没有所谓的环形队列&#xff0c;环形队列只是基于数组线性空间来实现。 环形队列优点&#xff1a; 避免假溢出现象。&#xff08;因为在数组里&#xff0c;头尾指针只增加不减少&#xff0c;被删元素的空间再也不能被重新利用。会造成尾…

无锁环形队列的几种高效实现

1.环形队列是什么 队列是一种常用的数据结构&#xff0c;这种结构保证了数据是按照“先进先出”的原则进行操作的&#xff0c;即最先进去的元素也是最先出来的元素.环形队列是一种特殊的队列结构&#xff0c;保证了元素也是先进先出的&#xff0c;但与一般队列的区别是&#…