1 /* -*- mode: c++ -*- 2 * The contents of this file are subject to the Mozilla Public 3 * License Version 1.1 (the "License"); you may not use this file 4 * except in compliance with the License. You may obtain a copy of 5 * the License at http://www.mozilla.org/MPL/ 6 * 7 * Software distributed under the License is distributed on an "AS 8 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 9 * implied. See the License for the specific language governing 10 * rights and limitations under the License. 11 * 12 * The Original Code is the Sablotron XSLT Processor. 13 * 14 * The Initial Developer of the Original Code is Ginger Alliance Ltd. 15 * Portions created by Ginger Alliance are Copyright (C) 2000-2002 16 * Ginger Alliance Ltd. All Rights Reserved. 17 * 18 * Contributor(s): 19 * 20 * Alternatively, the contents of this file may be used under the 21 * terms of the GNU General Public License Version 2 or later (the 22 * "GPL"), in which case the provisions of the GPL are applicable 23 * instead of those above. If you wish to allow use of your 24 * version of this file only under the terms of the GPL and not to 25 * allow others to use your version of this file under the MPL, 26 * indicate your decision by deleting the provisions above and 27 * replace them with the notice and other provisions required by 28 * the GPL. If you do not delete the provisions above, a recipient 29 * may use your version of this file under either the MPL or the 30 * GPL. 31 */ 32 33 #if !defined(OutputHIncl) 34 #define OutputHIncl 35 36 // GP: clean 37 38 #include "datastr.h" 39 #include "utf8.h" 40 #include "encoding.h" 41 42 class DataLine; // see uri.h 43 44 enum OutputMethod 45 { 46 OUTPUT_XML, 47 OUTPUT_HTML, 48 OUTPUT_TEXT, 49 OUTPUT_XHTML, 50 OUTPUT_UNKNOWN 51 }; 52 53 enum EscMode 54 { 55 ESCAPING_NONE, 56 ESCAPING_URI, 57 ESCAPING_ATTR, 58 // ESCAPING_CDATA, - use ESCAPING_NONE 59 ESCAPING_LT_AMP, 60 ESCAPING_HTML_URI, 61 ESCAPING_HTML_ATTR 62 }; 63 64 enum SAXOutputType 65 { 66 SAXOUTPUT_NONE, 67 //hard copy, no translations, no hidden ns.... 68 SAXOUTPUT_COPY_TREE, 69 //for physical output, hidden ns, aliasing 70 SAXOUTPUT_AS_PHYSICAL, 71 //as physical, but use expat like names 72 SAXOUTPUT_INT_PHYSICAL 73 }; 74 75 #define THE_NAMESPACE_SEPARATOR '`' 76 77 // the following must match the size of outputStringAtts[] - 1 78 // as defined in output.cpp 79 #define STRING_ITEMS_COUNT 8 80 81 // constants for special values of precedence for xsl:output attributes 82 // use for OutputDefinition::setItemStr and setItemEQName 83 84 // specify only if not yet specified, otherwise no error 85 #define OUTPUT_PRECEDENCE_WEAKEST -1 86 // override, no error 87 #define OUTPUT_PRECEDENCE_STRONGEST -2 88 // for internal use only 89 #define OUTPUT_PRECEDENCE_UNSPECIFIED -3 90 91 // 92 // StrPrec 93 // string with (import) precedence 94 // unspecified: precedence = -1 95 // to set, new precedence must be less than existing (unless existing == -1) 96 // special values of new precedence: override without checking (-1), set only if unspecified (-2) 97 // 98 99 class StrPrec 100 { 101 102 public: StrPrec()103 StrPrec() 104 { 105 precedence = OUTPUT_PRECEDENCE_UNSPECIFIED; 106 }; 107 // sets the string if new precedence is stronger 108 // returns TRUE if new pref is non-negative and equal to old (does not set in this case) 109 Bool set(const Str& newString, int newPrecedence); get()110 const Str& get() const 111 { 112 return string; 113 } 114 private: 115 Str string; 116 int precedence; 117 }; 118 119 // 120 // EQNamePrec 121 // same as StrPrec but holding EQName 122 // 123 124 class EQNamePrec 125 { 126 127 public: EQNamePrec()128 EQNamePrec() 129 { 130 precedence = OUTPUT_PRECEDENCE_UNSPECIFIED; 131 }; 132 // sets the string if new precedence is stronger 133 // returns TRUE if new pref is non-negative and equal to old (does not set in this case) 134 Bool set(const EQName& newName, int newPrecedence); get()135 const EQName& get() const 136 { 137 return name; 138 } 139 private: 140 EQName name; 141 int precedence; 142 }; 143 144 // 145 // OutputDef 146 // stores the output-controlling information for an XSLT tree 147 // 148 149 #define OUTPUT_BUFFER_LIMIT 1024 150 #define OUTPUT_BUFFER_SIZE OUTPUT_BUFFER_LIMIT + 64 151 152 153 #define HTML_SPECIAL TRUE 154 #define NOT_HTML_SPECIAL FALSE 155 156 class OutputDefinition 157 { 158 public: 159 OutputDefinition(); 160 ~OutputDefinition(); 161 // sets a string item 162 // itemId identifies the attribute code, 'value' is the new value 163 // 'caller' is the xsl:output element 164 // precedence is the current import precedence 165 // (may be OUTPUT_PRECEDENCE_STRONGEST to override, ..._WEAKEST to only set if unset) if !caller 166 eFlag setItemStr( 167 Sit S, XSL_ATT itemId, const Str& value, Vertex *caller, int precedence); 168 // sets an EQName item (@method or @cdata-sect-elems) 169 eFlag setItemEQName( 170 Sit S, XSL_ATT itemId, const EQName& value, Vertex *caller, int precedence); 171 eFlag setDefaults(Sit S); 172 const Str& getValueStr(XSL_ATT itemId) const; 173 const EQName& getValueEQName(XSL_ATT itemId) const; 174 Bool askEQNameList(XSL_ATT itemId, const EQName &what) const; 175 int getStatus(XSL_ATT itemId) const; 176 OutputMethod getMethod() const; 177 Bool getIndent() const; 178 const Str& getEncoding() const; 179 private: 180 StrPrec stringItems[STRING_ITEMS_COUNT]; 181 EQNamePrec 182 method; 183 EQNameList 184 cdataElems; 185 DataLine *targetDataLine; 186 void report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2); 187 }; 188 189 // 190 // 191 // PhysicalOutputterObj 192 // 193 // 194 195 class PhysicalOutputLayerObj 196 { 197 public: 198 PhysicalOutputLayerObj(CDesc encodingCD_); 199 ~PhysicalOutputLayerObj(); 200 eFlag setOptions(Sit S, DataLine *targetDataLine_, OutputDefinition *outDef_); 201 eFlag outputElementStart(Sit S, const Str& name, 202 const NamespaceStack& namespaces, const int namespace_index, 203 const StrStrList& atts, Bool isEmpty); 204 eFlag outputElementEnd(Sit S, const Str& name, Bool isEmpty); 205 eFlag outputText(Sit S, const Str& contents, Bool outputEscaping, Bool inHTMLSpecial); 206 eFlag outputComment(Sit S, const Str& contents); 207 eFlag outputCDataSection(Sit S, const Str& contents); 208 eFlag outputPI(Sit S, const Str& target, const Str& data); 209 eFlag outputDTD(Sit S, const Str& name, const Str& publicId, const Str& systemId); 210 eFlag outputTrailingNewline(Sit S); 211 eFlag outputDone(Sit S); 212 eFlag setMethodByDefault(Sit S, OutputMethod method_); getDataLine()213 DataLine* getDataLine() { return targetDataLine; }; 214 eFlag close(Sit S); 215 private: 216 DataLine *targetDataLine; 217 OutputDefinition *outDef; 218 OutputMethod method; 219 Bool indent; 220 Bool after_markup; //pc 221 int level; //pc 222 char buffer[OUTPUT_BUFFER_SIZE], 223 smallBuf[SMALL_BUFFER_SIZE]; 224 int curr; 225 Str encoding; 226 CDesc encodingCD; 227 Bool defaultNSWas; 228 eFlag sendOut(Sit S, const char* data, int length, EscMode escapeMode); 229 eFlag sendOutUntil(Sit S, const char* & data, int length, 230 EscMode escapeMode, const char* stoppingText); 231 int writeCharacterRef(char* dest, const char *src, EscMode escapeMode); 232 eFlag flushBuffer(Sit S); 233 void report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2); 234 }; 235 236 // 237 // 238 // OutputterObj 239 // 240 // 241 242 //output document (for multiple document output) 243 enum OutdocState { 244 OUTDOC_NEW, 245 OUTDOC_ACTIVE, 246 OUTDOC_FINISHED 247 }; 248 249 class OutputterObj; 250 class OutputDocument 251 { 252 public: OutputDocument(Str h,OutputDefinition * d)253 OutputDocument(Str h, OutputDefinition *d) : 254 href (h), outputter(NULL), state(OUTDOC_NEW), def(d) {}; 255 ~OutputDocument(); 256 OutputterObj* setOutputter(OutputterObj* new_); getOutputter()257 OutputterObj* getOutputter() { return outputter; }; getDefinition()258 OutputDefinition* getDefinition() { return def; }; getState()259 OutdocState getState() { return state; }; setState(OutdocState s)260 void setState(OutdocState s) { state = s; }; 261 eFlag finish(Sit S); getHref()262 Str &getHref() { return href; }; getURI()263 Str &getURI() { return uri; }; setURI(Str & val)264 void setURI(Str& val) { uri = val; }; 265 private: 266 Str href; 267 OutputterObj *outputter; 268 OutdocState state; 269 OutputDefinition *def; 270 Str uri; 271 }; 272 273 //following structures are used for correct namespace exclusions 274 class SubtreeInfo; 275 276 enum OutputterState 277 { 278 STATE_OUTSIDE = 0, 279 STATE_IN_MARKUP, 280 STATE_IN_ELEMENT, 281 STATE_IN_ATTRIBUTE, 282 STATE_IN_COMMENT, 283 STATE_IN_PI, 284 STATE_DONE, 285 STATE_UNDEFINED 286 }; 287 288 struct OutputHistoryItem 289 { 290 int flags; 291 int firstOwnNS; 292 OutputDocument *document; 293 OutputDocument *useDocument; 294 }; 295 296 typedef PList<OutputHistoryItem*> OutputHistory; 297 298 // 299 // FrontMatter 300 // 301 302 enum FrontMatterKind 303 { 304 FM_TEXT, 305 FM_COMMENT, 306 FM_PI 307 }; 308 309 struct FrontMatterItem 310 { 311 FrontMatterKind kind; 312 Str string1, string2; 313 Bool disableEsc; 314 }; 315 316 class FrontMatter : public PList<FrontMatterItem*> 317 { 318 public: 319 eFlag appendConstruct(Sit S, FrontMatterKind kind, const Str& string1, 320 const Str& string2, Bool disableEsc); 321 void report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2); 322 }; 323 324 325 class OutputterObj 326 { 327 public: 328 OutputterObj(); 329 ~OutputterObj(); 330 eFlag setOptions(Sit S, DataLine *targetDataLine_, OutputDefinition *outDef_); 331 eFlag setOptionsSAX(Sit S, SAXHandler *streaming_, void *userData, SAXOutputType saxout_); 332 eFlag eventBeginOutput(Sit S); 333 //_PH_ used for subtree serialization, ends with eventEndOutput 334 eFlag eventBeginSubtree(Sit S); 335 eFlag eventElementStart(Sit S, const EQName& name); 336 eFlag eventElementEnd(Sit S, const EQName& name); 337 eFlag eventAttributeStart(Sit S, const EQName& name); 338 eFlag eventAttributeEnd(Sit S); 339 eFlag eventCommentStart(Sit S); 340 eFlag eventCommentEnd(Sit S); 341 //eFlag eventExcludeNS(Sit S, UriList &exNS); 342 eFlag eventNamespace(Sit S, const Str& prefix, const Str& uri, 343 Bool hidden = FALSE); 344 eFlag eventPIStart(Sit S, const Str& name); 345 eFlag eventPIEnd(Sit S); 346 eFlag eventData(Sit S, const Str& data, Bool hardCData = FALSE); 347 eFlag eventCDataSection(Sit S, const Str& data); 348 eFlag eventDisableEscapingForNext(Sit S); 349 eFlag eventEndOutput(Sit S, Bool closePhysical = false); 350 eFlag eventTrailingNewline(Sit S); 351 eFlag setDocumentForLevel(Sit S, OutputDocument *doc); 352 OutputDocument* getDocumentForLevel(Bool forElement); getSAXOutputType()353 SAXOutputType getSAXOutputType() { return mySAXOutputType; }; getPhysical()354 PhysicalOutputLayerObj* getPhysical() { return physical; }; 355 private: 356 eFlag reportCurrData(Sit S, Bool hardCData = FALSE); 357 eFlag reportStartTag(Sit S, Bool isEmpty); 358 eFlag throwInMeta(Sit S); 359 Str* nameForSAX(Sit S, const EQName& q); 360 void pushLevel(const EQName& name); 361 // void popLevel(); getLevel()362 int getLevel() 363 { 364 return history.number() - 1; //ignore the '/' frame 365 }; getFlags()366 int getFlags() 367 { 368 return (history.number()? history.last() -> flags : 0); 369 } getFirstOwnNS()370 int getFirstOwnNS() 371 { 372 return (history.number()? history.last() -> firstOwnNS : 0); 373 } 374 Bool nsExcluded(Sit S, Str & uri); 375 eFlag reportXMLDeclIfMust(Sit S); 376 eFlag reportDTDIfMust(Sit S, const EQName& docElementName); 377 eFlag reportFront(Sit S); 378 void report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2); 379 // 380 PhysicalOutputLayerObj *physical; 381 SAXHandler *mySAXHandler; 382 void *mySAXUserData; 383 SAXOutputType mySAXOutputType; 384 OutputDefinition *outDef; 385 OutputMethod method; 386 CDesc encodingCD; 387 OutputterState state; 388 Bool outputEscaping; 389 DStr currData; 390 Str 391 currPIName; 392 EQName 393 currElement, 394 currAttName; 395 NamespaceStack 396 currNamespaces; 397 EQNameStrList 398 currAtts; 399 OutputHistory history; 400 Bool noElementYet, 401 noHeadYet, 402 delayedDTD; 403 FrontMatter front; 404 }; 405 406 407 #endif // OutputHIncl 408