如何在XercesC中使用SAX解析器获取DTD内部子集?
用XercesC 3.2.4的SAX解析器提取XML内部DTD子集
在XercesC的SAX2框架中,你可以通过扩展DefaultHandler类并重写特定回调方法来捕获内部DTD子集,核心是利用internalSubset方法——该方法会在解析器遇到内部DTD子集时触发。
实现步骤
- 自定义一个继承自
xercesc::DefaultHandler的处理类,重写internalSubset方法来保存内部子集内容。 - 可选重写
startDTD和endDTD方法,用于标记DTD解析的起止,辅助确认内部子集的上下文。
代码示例
#include <xercesc/sax2/DefaultHandler.hpp> #include <xercesc/sax2/SAX2XMLReader.hpp> #include <xercesc/sax2/XMLReaderFactory.hpp> #include <xercesc/util/XMLString.hpp> #include <iostream> #include <string> XERCES_CPP_NAMESPACE_USE class DTDHandler : public DefaultHandler { private: std::string internalSubsetContent; public: // 捕获内部DTD子集内容 void internalSubset(const XMLCh* name, const XMLCh* publicId, const XMLCh* systemId, const XMLCh* internalSubset) override { if (internalSubset != nullptr) { char* subsetStr = XMLString::transcode(internalSubset); internalSubsetContent = subsetStr; XMLString::release(&subsetStr); } } // 可选:标记DTD解析开始 void startDTD(const XMLCh* name, const XMLCh* publicId, const XMLCh* systemId) override { char* dtdName = XMLString::transcode(name); std::cout << "开始解析DTD: " << dtdName << std::endl; XMLString::release(&dtdName); } // 获取保存的内部子集内容 const std::string& getInternalSubset() const { return internalSubsetContent; } // 处理解析错误 void error(const SAXParseException& e) override { char* msg = XMLString::transcode(e.getMessage()); std::cerr << "解析错误: " << msg << " 行号: " << e.getLineNumber() << std::endl; XMLString::release(&msg); } }; int main() { // 初始化XercesC环境 try { XMLPlatformUtils::Initialize(); } catch (const XMLException& e) { char* msg = XMLString::transcode(e.getMessage()); std::cerr << "初始化失败: " << msg << std::endl; XMLString::release(&msg); return 1; } // 创建SAX解析器实例 SAX2XMLReader* parser = XMLReaderFactory::createXMLReader(); parser->setFeature(XMLUni::fgSAX2CoreValidation, false); parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, false); // 绑定自定义处理类 DTDHandler handler; parser->setContentHandler(&handler); parser->setDTDHandler(&handler); parser->setErrorHandler(&handler); // 解析目标XML文件 try { parser->parse("your_target.xml"); std::cout << "内部DTD子集内容:\n" << handler.getInternalSubset() << std::endl; } catch (const XMLException& e) { char* msg = XMLString::transcode(e.getMessage()); std::cerr << "解析异常: " << msg << std::endl; XMLString::release(&msg); } catch (const SAXParseException& e) { char* msg = XMLString::transcode(e.getMessage()); std::cerr << "解析错误: " << msg << " 行号: " << e.getLineNumber() << std::endl; XMLString::release(&msg); } catch (...) { std::cerr << "未知解析错误" << std::endl; } // 清理资源 delete parser; XMLPlatformUtils::Terminate(); return 0; }
关键说明
internalSubset方法的最后一个参数internalSubset就是内部DTD子集的XMLCh编码字符串,需用XMLString::transcode转换为本地编码(如UTF-8)后保存。- 默认情况下XercesC的SAX解析器会处理DTD,若之前关闭了DTD相关特性,需重新开启以确保回调触发。
- 代码包含基础错误处理逻辑,可根据实际需求调整。
内容的提问来源于stack exchange,提问作者user23321476
相关产品推荐
相关产品推荐

