⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pxml.cxx

📁 pwlib源码库
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/* * pxml.cxx * * XML parser support * * Portable Windows Library * * Copyright (c) 2002 Equivalence Pty. Ltd. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is Portable Windows Library. * * The Initial Developer of the Original Code is Equivalence Pty. Ltd. * * Contributor(s): ______________________________________. * * $Log: pxml.cxx,v $ * Revision 1.42  2005/05/12 05:30:16  csoutheren * Ensured error location is initialised * * Revision 1.41  2004/10/23 10:58:15  ykiryanov * Added ifdef _WIN32_WCE for PocketPC 2003 SDK port * * Revision 1.40  2004/10/12 23:28:08  csoutheren * Fixed problem with bogus DOCTYPE being output * * Revision 1.39  2004/04/21 00:35:02  csoutheren * Added a stream parser for protocols like XMPP where each child of the root is to be considered a separate document/message. * Thanks to Federico Pinna and Reitek S.p.A. * * Revision 1.38  2004/04/09 06:52:17  rjongbloed * Removed #pargma linker command for /delayload of DLL as documentations sais that *   you cannot do this. * * Revision 1.37  2004/02/23 23:52:20  csoutheren * Added pragmas to avoid every Windows application needing to include libs explicitly * * Revision 1.36  2004/01/17 18:12:59  csoutheren * Changed to use PString::MakeEmpty * * Revision 1.35  2003/05/14 02:50:53  rjongbloed * Simplified name space initialisation * * Revision 1.34  2003/05/06 07:55:25  craigs * Fixed problem with initialising XML parser for namespaces * * Revision 1.33  2003/04/27 23:53:30  craigs * Removed deprecated options * * Revision 1.32  2003/04/16 08:00:19  robertj * Windoes psuedo autoconf support * * Revision 1.31  2003/04/08 12:47:07  craigs * Fixed problem with handling of CDATA * * Revision 1.30  2003/04/08 05:08:41  craigs * Fixed problems with additional spaces being included with metasequences * * Revision 1.29  2003/04/02 09:13:55  rogerh * Add type casts because the variable 'expat' is now a void * * * Revision 1.28  2003/03/31 06:20:56  craigs * Split the expat wrapper from the XML file handling to allow reuse of the parser * * Revision 1.27  2003/01/13 02:14:02  robertj * Improved error logging for auto-loaded XML * * Revision 1.26  2002/12/16 06:38:59  robertj * Added ability to specify certain elemets (by name) that are exempt from *   the indent formatting. Useful for XML/RPC where leading white space is *   not ignored by all servers. * * Revision 1.25  2002/12/10 04:41:16  robertj * Added test for URL being empty, don't try and run auto load in background. * * Revision 1.24  2002/11/26 05:53:45  craigs * Added ability to auto-reload from URL * * Revision 1.23  2002/11/21 08:08:52  craigs * Changed to not overwrite XML data if load fails * * Revision 1.22  2002/11/19 07:37:25  craigs * Added locking functions and LoadURL function * * Revision 1.21  2002/11/06 22:47:25  robertj * Fixed header comment (copyright etc) * */// This depends on the expat XML library by Jim Clark// See http://www.jclark.com/xml/expat.html for more information#include <ptlib.h>#ifdef __GNUC__#pragma implementation "pxml.h"#endif#include <ptclib/pxml.h>#if P_EXPAT#include <expat.h>#define CACHE_BUFFER_SIZE   1024#define	XMLSETTINGS_OPTIONS	(NewLineAfterElement)#ifdef _MSC_VER#ifndef _WIN32_WCE#pragma comment(lib, P_EXPAT_LIBRARY)#endif // !_WIN32_WCE#endif////////////////////////////////////////////////////static void PXML_StartElement(void * userData, const char * name, const char ** attrs){  ((PXMLParser *)userData)->StartElement(name, attrs);}static void PXML_EndElement(void * userData, const char * name){  ((PXMLParser *)userData)->EndElement(name);}static void PXML_CharacterDataHandler(void * userData, const char * data, int len){  ((PXMLParser *)userData)->AddCharacterData(data, len);}static void PXML_XmlDeclHandler(void * userData, const char * version, const char * encoding, int standalone){  ((PXMLParser *)userData)->XmlDecl(version, encoding, standalone);}static void PXML_StartDocTypeDecl(void * userData,		            const char * docTypeName,		            const char * sysid,		            const char * pubid,			             int hasInternalSubSet){  ((PXMLParser *)userData)->StartDocTypeDecl(docTypeName, sysid, pubid, hasInternalSubSet);}static void PXML_EndDocTypeDecl(void * userData){  ((PXMLParser *)userData)->EndDocTypeDecl();}static void PXML_StartNamespaceDeclHandler(void *userData,                                 const XML_Char *prefix,                                 const XML_Char *uri){  ((PXMLParser *)userData)->StartNamespaceDeclHandler(prefix, uri);}static void PXML_EndNamespaceDeclHandler(void *userData, const XML_Char *prefix){  ((PXMLParser *)userData)->EndNamespaceDeclHandler(prefix);}PXMLParser::PXMLParser(int _options)  : options(_options){  if (options < 0)    options = 0;  if ((options & WithNS) != 0)    expat = XML_ParserCreateNS(NULL, '|');  else    expat = XML_ParserCreate(NULL);  XML_SetUserData((XML_Parser)expat, this);  XML_SetElementHandler      ((XML_Parser)expat, PXML_StartElement, PXML_EndElement);  XML_SetCharacterDataHandler((XML_Parser)expat, PXML_CharacterDataHandler);  XML_SetXmlDeclHandler      ((XML_Parser)expat, PXML_XmlDeclHandler);  XML_SetDoctypeDeclHandler  ((XML_Parser)expat, PXML_StartDocTypeDecl, PXML_EndDocTypeDecl);  XML_SetNamespaceDeclHandler((XML_Parser)expat, PXML_StartNamespaceDeclHandler, PXML_EndNamespaceDeclHandler);  rootElement = NULL;  currentElement = NULL;  lastElement    = NULL;}PXMLParser::~PXMLParser(){  XML_ParserFree((XML_Parser)expat);}PXMLElement * PXMLParser::GetXMLTree() const{   return rootElement; }PXMLElement * PXMLParser::SetXMLTree(PXMLElement * newRoot){   PXMLElement * oldRoot = rootElement;  rootElement = newRoot;   return oldRoot;}BOOL PXMLParser::Parse(const char * data, int dataLen, BOOL final){  return XML_Parse((XML_Parser)expat, data, dataLen, final) != 0;  }void PXMLParser::GetErrorInfo(PString & errorString, PINDEX & errorCol, PINDEX & errorLine){  XML_Error err = XML_GetErrorCode((XML_Parser)expat);  errorString = PString(XML_ErrorString(err));  errorCol    = XML_GetCurrentColumnNumber((XML_Parser)expat);  errorLine   = XML_GetCurrentLineNumber((XML_Parser)expat);}void PXMLParser::StartElement(const char * name, const char **attrs){  PXMLElement * newElement = new PXMLElement(currentElement, name);  if (currentElement != NULL)    currentElement->AddSubObject(newElement, FALSE);  while (attrs[0] != NULL) {    newElement->SetAttribute(PString(attrs[0]), PString(attrs[1]));    attrs += 2;  }  currentElement = newElement;  lastElement    = NULL;  if (rootElement == NULL)    rootElement = currentElement;}void PXMLParser::EndElement(const char * /*name*/){  currentElement = currentElement->GetParent();  lastElement    = NULL;}void PXMLParser::AddCharacterData(const char * data, int len){  PString str(data, len);  if (lastElement != NULL) {    PAssert(!lastElement->IsElement(), "lastElement set by non-data element");    lastElement->SetString(lastElement->GetString() + str, FALSE);  } else {    PXMLData * newElement = new PXMLData(currentElement, str);    if (currentElement != NULL)      currentElement->AddSubObject(newElement, FALSE);    lastElement = newElement;  } }void PXMLParser::XmlDecl(const char * _version, const char * _encoding, int _standAlone){  version    = _version;  encoding   = _encoding;  standAlone = _standAlone;}void PXMLParser::StartDocTypeDecl(const char * /*docTypeName*/,		                              const char * /*sysid*/,				                          const char * /*pubid*/,				                          int /*hasInternalSubSet*/){}void PXMLParser::EndDocTypeDecl(){}void PXMLParser::StartNamespaceDeclHandler(const XML_Char * /*prefix*/,                                            const XML_Char * /*uri*/){}void PXMLParser::EndNamespaceDeclHandler(const XML_Char * /*prefix*/){}///////////////////////////////////////////////////////////////////////////////////////////////PXML::PXML(int options, const char * noIndentElements)  : PXMLBase(options) {  Construct(options, noIndentElements);}PXML::PXML(const PString & data, int options, const char * noIndentElements)  : PXMLBase(options) {  Construct(options, noIndentElements);  Load(data);}PXML::~PXML(){  autoLoadTimer.Stop();  RemoveAll();}PXML::PXML(const PXML & xml)  : noIndentElements(xml.noIndentElements){  Construct(xml.options, NULL);  loadFromFile = xml.loadFromFile;  loadFilename = xml.loadFilename;  version      = xml.version;  encoding     = xml.encoding;  standAlone   = xml.standAlone;  PWaitAndSignal m(xml.rootMutex);  PXMLElement * oldRootElement = xml.rootElement;  if (oldRootElement != NULL)    rootElement = (PXMLElement *)oldRootElement->Clone(NULL);}void PXML::Construct(int _options, const char * _noIndentElements){  rootElement    = NULL;  options        = _options > 0 ? _options : 0;  loadFromFile   = FALSE;  standAlone     = -2;  errorCol       = 0;  errorLine      = 0;  if (_noIndentElements != NULL)    noIndentElements = PString(_noIndentElements).Tokenise(' ', FALSE);}PXMLElement * PXML::SetRootElement(const PString & documentType){  PWaitAndSignal m(rootMutex);  if (rootElement != NULL)    delete rootElement;  rootElement = new PXMLElement(rootElement, documentType);  return rootElement;}PXMLElement * PXML::SetRootElement(PXMLElement * element){  PWaitAndSignal m(rootMutex);  if (rootElement != NULL)    delete rootElement;  rootElement = element;  return rootElement;}BOOL PXML::IsDirty() const{  PWaitAndSignal m(rootMutex);  if (rootElement == NULL)    return FALSE;  return rootElement->IsDirty();}PCaselessString PXML::GetDocumentType() const{   PWaitAndSignal m(rootMutex);  if (rootElement == NULL)    return PCaselessString();  return rootElement->GetName();}BOOL PXML::LoadFile(const PFilePath & fn, int _options){  PTRACE(4, "XML\tLoading file " << fn);  PWaitAndSignal m(rootMutex);  if (_options >= 0)    options = _options;  loadFilename = fn;  loadFromFile = TRUE;  PFile file;  if (!file.Open(fn, PFile::ReadOnly)) {    errorString = "File open error" & file.GetErrorText();    return FALSE;  }  off_t len = file.GetLength();  PString data;  if (!file.Read(data.GetPointer(len + 1), len)) {    errorString = "File read error" & file.GetErrorText();    return FALSE;  }  data[(PINDEX)len] = '\0';  return Load(data);}BOOL PXML::LoadURL(const PURL & url){  return LoadURL(url, PMaxTimeInterval, -1);}BOOL PXML::LoadURL(const PURL & url, const PTimeInterval & timeout, int _options){  if (url.IsEmpty()) {    errorString = "Cannot load empty URL";    errorCol = errorLine = 0;    return FALSE;  }  PTRACE(4, "XML\tLoading URL " << url);  PString data;  if (url.GetScheme() == "file")     return LoadFile(url.AsFilePath());  PHTTPClient client;  PINDEX contentLength;  PMIMEInfo outMIME, replyMIME;  // make sure we do not hang around for ever  client.SetReadTimeout(timeout);  // get the resource header information  if (!client.GetDocument(url, outMIME, replyMIME)) {    errorString = PString("Cannot load URL") & url.AsString();    errorCol = errorLine = 0;    return FALSE;  }  // get the length of the data  if (!replyMIME.Contains(PHTTPClient::ContentLengthTag))    contentLength = (PINDEX)replyMIME[PHTTPClient::ContentLengthTag].AsUnsigned();  else    contentLength = P_MAX_INDEX;  // download the resource into memory  PINDEX offs = 0;  for (;;) {    PINDEX len;    if (contentLength == P_MAX_INDEX)      len = CACHE_BUFFER_SIZE;    else if (offs == contentLength)      break;    else      len = PMIN(contentLength = offs, CACHE_BUFFER_SIZE);    if (!client.Read(offs + data.GetPointer(offs + len), len))      break;    len = client.GetLastReadCount();    offs += len;  }  return Load(data, _options);}BOOL PXML::StartAutoReloadURL(const PURL & url,                               const PTimeInterval & timeout,                               const PTimeInterval & refreshTime,                              int _options){  if (url.IsEmpty()) {    autoLoadError = "Cannot auto-load empty URL";    return FALSE;  }  PWaitAndSignal m(autoLoadMutex);  autoLoadTimer.Stop();  SetOptions(_options);  autoloadURL      = url;  autoLoadWaitTime = timeout;  autoLoadError.MakeEmpty();  autoLoadTimer.SetNotifier(PCREATE_NOTIFIER(AutoReloadTimeout));  BOOL stat = AutoLoadURL();  autoLoadTimer = refreshTime;  return stat;}void PXML::AutoReloadTimeout(PTimer &, INT){  PThread::Create(PCREATE_NOTIFIER(AutoReloadThread), PThread::AutoDeleteThread);}void PXML::AutoReloadThread(PThread &, INT){  PWaitAndSignal m(autoLoadMutex);  OnAutoLoad(AutoLoadURL());  autoLoadTimer.Reset();}void PXML::OnAutoLoad(BOOL ok){  PTRACE_IF(3, !ok, "XML\tFailed to load XML: " << GetErrorString());}BOOL PXML::AutoLoadURL(){  BOOL stat = LoadURL(autoloadURL, autoLoadWaitTime);  if (stat)    autoLoadError.MakeEmpty();  else     autoLoadError = GetErrorString() + psprintf(" at line %i, column %i", GetErrorLine(), GetErrorColumn());  return stat;}BOOL PXML::StopAutoReloadURL(){  PWaitAndSignal m(autoLoadMutex);  autoLoadTimer.Stop();  return TRUE;}BOOL PXML::Load(const PString & data, int _options){  if (_options >= 0)    options = _options;  BOOL stat = FALSE;  PXMLElement * loadingRootElement = NULL;  {    PXMLParser parser(options);    int done = 1;    stat = parser.Parse(data, data.GetLength(), done) != 0;      if (!stat)      parser.GetErrorInfo(errorString, errorCol, errorLine);    version    = parser.GetVersion();    encoding   = parser.GetEncoding();    standAlone = parser.GetStandAlone();    loadingRootElement = parser.GetXMLTree();  }  if (stat) {    if (loadingRootElement == NULL) {      errorString = "XML\tFailed to create root node in XML!";      return FALSE;    }    else {      PWaitAndSignal m(rootMutex);      if (rootElement != NULL) {        delete rootElement;        rootElement = NULL;      }      rootElement = loadingRootElement;      PTRACE(4, "XML\tLoaded XML " << rootElement->GetName());    }    OnLoaded();  }  return stat;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -