📄 xmloutputeventhandler.cxx
字号:
// Copyright (c) 1997 James Clark// See the file COPYING for copying permission.#ifdef __GNUG__#pragma implementation#endif#include "config.h"#include "XmlOutputEventHandler.h"#include "XmlOutputMessages.h"#include "Message.h"#include "MessageArg.h"#include "macros.h"#if 0#include "UTF8CodingSystem.h"#endif#include "InputSource.h"#include "StorageManager.h"#include <string.h>#ifdef SP_NAMESPACEnamespace SP_NAMESPACE {#endifinlinevoid operator+=(StringC &str, const char *s){ while (*s) str += *s++;}inlinevoid XmlOutputEventHandler::closeCdataSection(){ useCdata_ = 0; if (inCdata_) { os() << "]]>"; inCdata_ = 0; nCdataEndMatched_ = 0; }}const char RE = '\r';XmlOutputEventHandler::Options::Options(){ memset(this, 0, sizeof(*this));}staticvoid escape(OutputCharStream &s, Char c){ s << "&#" << (unsigned long)c << ";";}XmlOutputEventHandler::XmlOutputEventHandler(const Options &options, OutputCharStream *os, const StringC &encodingName, const Ptr<ExtendEntityManager> &entityManager, const CharsetInfo &systemCharset, Messenger *mgr): options_(options), os_(os), entityManager_(entityManager), systemCharset_(&systemCharset), mgr_(mgr), inDtd_(0), inCdata_(0), useCdata_(0), nCdataEndMatched_(0), namecaseGeneral_(0){ os_->setEscaper(escape); *os_ << "<?xml version=\"1.0\""; if (encodingName.size()) *os_ << " encoding=\"" << encodingName << '"'; *os_ << "?>" << RE;}XmlOutputEventHandler::~XmlOutputEventHandler(){ os() << RE; delete os_;}void XmlOutputEventHandler::message(MessageEvent *event){ mgr_->dispatchMessage(event->message()); ErrorCountEventHandler::message(event);}void XmlOutputEventHandler::sgmlDecl(SgmlDeclEvent *event){ const Syntax &syntax = event->instanceSyntax(); if (syntax.namecaseGeneral()) { namecaseGeneral_ = 1; syntax.generalSubstTable()->inverseTable(lowerSubst_); } delete event;}void XmlOutputEventHandler::data(DataEvent *event){ if (useCdata_) outputCdata(event->data(), event->dataLength()); else outputData(event->data(), event->dataLength(), 0); delete event;}void XmlOutputEventHandler::startElement(StartElementEvent *event){ // This shouldn't happen (although useCdata_ can be true). if (inCdata_) { inCdata_ = 0; nCdataEndMatched_ = 0; os() << "]]>"; } os() << '<' << generalName(event->name(), nameBuf_); size_t nAttributes = event->attributes().size(); for (size_t i = 0; i < nAttributes; i++) outputAttribute(event->attributes(), i); if (options_.nlInTag) os() << RE; if (options_.cdata && event->elementType()->definition()->declaredContent() == ElementDefinition::cdata) useCdata_ = 1; if (options_.empty && event->elementType()->definition()->declaredContent() == ElementDefinition::empty) os() << "/>"; else os() << '>'; delete event;}void XmlOutputEventHandler::outputAttribute(const AttributeList &attributes, size_t i){ const AttributeValue *value = attributes.value(i); if (!value) return; const Text *text; const StringC *string; AttributeValue::Type type = value->info(text, string); if (type == AttributeValue::implied) return; if (options_.nlInTag) os() << RE; else os() << ' '; os() << generalName(attributes.name(i), nameBuf_) << "=\""; if (type == AttributeValue::cdata) { TextIter iter(*text); TextItem::Type type; const Char *p; size_t length; const Location *loc; while (iter.next(type, p, length, loc)) { switch (type) { case TextItem::data: case TextItem::cdata: outputData(p, length, 1); break; case TextItem::sdata: { mgr_->setNextLocation(loc->origin()->parent()); const Entity *entity = loc->origin()->asEntityOrigin()->entity(); mgr_->message(XmlOutputMessages::sdataEntityReference, StringMessageArg(entity->name())); os() << '&' << entity->name() << ';'; } break; case TextItem::nonSgml: // FIXME break; default: break; } } } else if (attributes.def()->def(i)->isEntity()) os() << *string; else os() << generalName(*string, nameBuf_); os() << '"';}void XmlOutputEventHandler::endElement(EndElementEvent *event){ closeCdataSection(); if (options_.empty && event->elementType()->definition()->declaredContent() == ElementDefinition::empty) ; else { os() << "</" << generalName(event->name(), nameBuf_);#if 0 if (options_.nlInTag) os() << RE;#endif os() << '>'; } delete event;}static Boolean isXmlS(Char c){ switch (c) { case ' ': case '\r': case '\n': case '\t': return 1; } return 0;}static Boolean containsQuestionLt(const Char *s, size_t n){ for (; n > 1; n--, s++) if (*s == '?' && s[1] == '>') return 1; return 0;}// These do not handle Unicode chars properly.// They treat all Unicode chars >= 170 as name start charactersstatic Boolean isXmlNameStartChar(Char c){ switch (c) { case ':': case '.': case '_': case '-': return 1; } if (c >= 170) return 1; if ('a' <= c && c <= 'z') return 1; if ('A' <= c && c <= 'Z') return 1; return 0;}static Boolean isXmlNameChar(Char c){ if (isXmlNameStartChar(c)) return 1; if ('0' <= c && c <= '9') return 1; return 0;}static Boolean startsWithXmlName(const Char *s, size_t n){ if (n == 0) return 0; if (!isXmlNameStartChar(*s)) return 0; for (s++, n--; n > 0; n--, s++) { if (isXmlS(*s)) return 1; if (!isXmlNameChar(*s)) return 0; } return 1;}void XmlOutputEventHandler::pi(PiEvent *event){ const Char *s = event->data(); size_t n = event->dataLength(); if (n >= 3 && s[0] == 'x' && s[1] == 'm' && s[2] == 'l' && (n == 3 || isXmlS(s[3]))) ; // Probably came from an encoding PI. else if (!startsWithXmlName(s, n)) { mgr_->setNextLocation(event->location()); mgr_->message(XmlOutputMessages::piNoName); } else if (options_.piEscape) { os() << "<?"; outputData(s, n, 0); os() << "?>"; } else if (containsQuestionLt(s, n)) { mgr_->setNextLocation(event->location()); mgr_->message(XmlOutputMessages::piQuestionLt); } else { os() << "<?"; os().write(s, n); os() << "?>"; } delete event;}void XmlOutputEventHandler::sdataEntity(SdataEntityEvent *event){ mgr_->setNextLocation(event->location().origin()->parent()); mgr_->message(XmlOutputMessages::sdataEntityReference, StringMessageArg(event->entity()->name())); os() << '&' << event->entity()->name() << ';'; delete event;}void XmlOutputEventHandler::externalDataEntity(ExternalDataEntityEvent *event){ mgr_->setNextLocation(event->location().origin()->parent()); mgr_->message(XmlOutputMessages::externalDataEntityReference, StringMessageArg(event->entity()->name())); os() << (options_.lower ? "<entity name=\"" : "<ENTITY NAME=\"") << event->entity()->name() << "\"/>"; delete event;}void XmlOutputEventHandler::subdocEntity(SubdocEntityEvent *event){ mgr_->setNextLocation(event->location().origin()->parent()); mgr_->message(XmlOutputMessages::subdocEntityReference, StringMessageArg(event->entity()->name())); os() << (options_.lower ? "<entity name=\"" : "<ENTITY NAME=\"") << event->entity()->name() << "\"/>"; delete event;}void XmlOutputEventHandler::startDtd(StartDtdEvent *event){ inDtd_ = 1; delete event;}void XmlOutputEventHandler::endDtd(EndDtdEvent *event){ inDtd_ = 0; delete event;}void XmlOutputEventHandler::maybeStartDoctype(Boolean &doctypeStarted, const Dtd &dtd){ if (doctypeStarted) return; doctypeStarted = 1; os() << "<!DOCTYPE " << dtd.documentElementType()->name() << " [" << RE;}void XmlOutputEventHandler::endProlog(EndPrologEvent *event){ const Dtd &dtd = event->dtd(); Boolean doctypeStarted = 0; if (options_.notation) { Dtd::ConstNotationIter iter(dtd.notationIter()); for (;;) { const Notation *notation = iter.nextTemp(); if (!notation) break; maybeStartDoctype(doctypeStarted, dtd); os() << "<!NOTATION " << generalName(notation->name(), nameBuf_); outputExternalId(*notation); os() << ">" << RE; if (notation->attributeDefTemp()) { mgr_->setNextLocation(notation->defLocation()); mgr_->message(XmlOutputMessages::notationAttributes,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -