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/
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.
12 * The Original Code is the Sablotron XSLT Processor.
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.
18 * Contributor(s): Marc Lehmann <pcg@goof.com>
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
45 #ifdef SABLOT_DEBUGGER
53 #define NONEMPTY_ELEMENT FALSE
54 #define EMPTY_ELEMENT TRUE
60 HTML_SCRIPT_OR_STYLE = 2,
64 #define IF_SAX1( FUNC )\
66 { mySAXHandler -> FUNC(mySAXUserData, S.getProcessor()); }}
67 #define IF_SAX2( FUNC, ARG1 )\
69 { mySAXHandler -> FUNC(mySAXUserData, S.getProcessor(), (ARG1)); }}
70 #define IF_SAX3( FUNC, ARG1, ARG2 )\
72 { mySAXHandler -> FUNC(mySAXUserData, S.getProcessor(), (ARG1), (ARG2)); }}
74 //macros on internal handler
75 #define IF_INT_SAX4( FUNC, ARG1, ARG2, ARG3 )\
77 { ((SAXHandlerInternal*)mySAXHandler) -> FUNC(mySAXUserData, S.getProcessor(), (ARG1), (ARG2), (ARG3)); }}
79 #define IF_PH1( FUNC )\
81 { physical -> FUNC(S); }}
82 #define IF_PH2( FUNC, ARG1)\
84 { physical -> FUNC(S, ARG1); }}
85 #define IF_PH3( FUNC, ARG1, ARG2 )\
87 { physical -> FUNC(S, (ARG1), (ARG2)); }}
89 // STRING_ITEMS_COUNT (output.h) must be in sync with the size
90 // of the following table:
92 XSL_ATT outputStringAtts[STRING_ITEMS_COUNT + 1] = {
93 XSLA_VERSION, XSLA_ENCODING, XSLA_OMIT_XML_DECL, XSLA_STANDALONE,
94 XSLA_DOCTYPE_PUBLIC, XSLA_DOCTYPE_SYSTEM, XSLA_INDENT, XSLA_MEDIA_TYPE,
98 const char* theEmptyHTML40Tags[] =
100 "area", "base", "basefont", "br", "col", "frame", "hr", "img",
101 "input", "isindex", "link", "meta", "param", NULL
104 const char* theURI_HTMLAtts[] =
108 "background", // BODY
109 "cite", // BLOCKQUOTE, Q, DEL, INS
111 "codebase", // OBJECT, APPLET
113 "href", // A, AREA, LINK, BASE
114 "longdesc", // IMG, FRAME, IFRAME
116 "src", // SCRIPT, INPUT, FRAME, IFRAME, IMG
117 "usemap", // IMG, INPUT, OBJECT
121 const char* theHTMLBooleanAtts[] =
139 const char* theHTMLNoEscapeTags[] =
146 // tags new lines should not be inserted after by indent
147 const char* theNoEolHTMLTags[] =
152 Bool isEmptyHTMLTag(const Str& name)
154 int ndx = lookupNoCase(name, theEmptyHTML40Tags);
155 // return TRUE iff found
156 return !!theEmptyHTML40Tags[ndx];
159 Bool isHTMLNoEscapeTag(const Str& name)
161 int ndx = lookupNoCase(name, theHTMLNoEscapeTags);
162 return !!theHTMLNoEscapeTags[ndx];
165 Bool isBooleanHTMLAtt(const Str& name)
167 int ndx = lookupNoCase(name, theHTMLBooleanAtts);
168 return !!theHTMLBooleanAtts[ndx];
171 // this should be improved by checking the name of the parent element
172 // see the element names in theURI_HTMLAtts
173 Bool isURI_HTMLAtt(const Str& name)
175 int ndx = lookupNoCase(name, theURI_HTMLAtts);
176 // return TRUE iff found
177 return !!theURI_HTMLAtts[ndx];
180 Bool isNoEolHTMLTag(const Str& name)
182 int ndx = lookupNoCase(name, theNoEolHTMLTags);
183 // return TRUE iff found
184 return !!theNoEolHTMLTags[ndx];
188 // StrPrec and EQNamePrec implementation
192 // returns -1 if oldPrec wins, +1 if newPrec wins, 0 if equal (usually error)
193 int cmpPrecedences(int oldPrec, int newPrec)
195 if (oldPrec == OUTPUT_PRECEDENCE_UNSPECIFIED ||
196 newPrec == OUTPUT_PRECEDENCE_STRONGEST ||
197 newPrec >= 0 && newPrec < oldPrec)
199 if (newPrec >= 0 && oldPrec == newPrec)
204 Bool StrPrec::set(const Str& newString, int newPrecedence)
206 int cmp = cmpPrecedences(precedence, newPrecedence);
207 // if new wins or there's a draw, set the value
211 precedence = newPrecedence;
213 // if cmp == 0, return TRUE
214 return cmp ? FALSE : TRUE;
217 Bool EQNamePrec::set(const EQName& newName, int newPrecedence)
219 int cmp = cmpPrecedences(precedence, newPrecedence);
220 // if new wins or there's a draw, set the value
224 precedence = newPrecedence;
226 // if cmp == 0, return TRUE
227 return cmp ? FALSE : TRUE;
234 Bool checkYesNo(const Str& what)
236 return(what == (const char*) "yes" || what == (const char*) "no");
239 OutputDefinition::OutputDefinition()
244 OutputDefinition::~OutputDefinition()
246 cdataElems.freeall(FALSE);
249 int lookupAttCode(XSL_ATT* table, XSL_ATT what)
252 for (i = 0; table[i] != XSLA_NONE && table[i] != what; i++) {};
253 return (table[i] == XSLA_NONE ? -1 : i);
256 eFlag OutputDefinition::setItemStr(Sit S, XSL_ATT itemId, const Str& value, Vertex *caller, int precedence)
259 precedence = caller -> getImportPrecedence();
262 case XSLA_OMIT_XML_DECL:
263 case XSLA_STANDALONE:
266 if (!checkYesNo(value))
268 S.setCurrVDoc(caller);
269 Err1(S, E1_ATTR_YES_NO, xslAttNames[itemId]);
273 int index = lookupAttCode(outputStringAtts, itemId);
275 if (stringItems[index].set(value, precedence))
277 S.setCurrVDoc(caller);
278 Warn1(S, W1_OUTPUT_ATTR, xslAttNames[itemId]);
283 eFlag OutputDefinition::setItemEQName(Sit S, XSL_ATT itemId, const EQName& value, Vertex *caller, int precedence)
286 precedence = caller -> getImportPrecedence();
289 case XSLA_CDATA_SECT_ELEMS:
290 cdataElems.append(new EQName(value)); break;
293 assert(itemId == XSLA_METHOD);
294 if (method.set(value, precedence))
296 S.setCurrVDoc(caller);
297 Warn1(S, W1_OUTPUT_ATTR, xslAttNames[itemId]);
304 const Str& OutputDefinition::getValueStr(XSL_ATT itemId) const
306 int index = lookupAttCode(outputStringAtts, itemId);
308 return stringItems[index].get();
311 const EQName& OutputDefinition::getValueEQName(XSL_ATT itemId) const
313 assert(itemId == XSLA_METHOD);
317 Bool OutputDefinition::askEQNameList(XSL_ATT itemId, const EQName &what) const
319 assert(itemId == XSLA_CDATA_SECT_ELEMS);
320 return (cdataElems.find(what) != NULL);
323 OutputMethod OutputDefinition::getMethod() const
325 const Str& method_ = getValueEQName(XSLA_METHOD).getLocal();
326 if (method_ == (const char*) "html")
328 else if (method_ == (const char*) "text")
330 else if (method_ == (const char*) "xml")
332 else if (method_ == (const char*) "xhtml")
334 else return OUTPUT_UNKNOWN;
337 const Str& OutputDefinition::getEncoding() const
339 return getValueStr(XSLA_ENCODING);
342 Bool OutputDefinition::getIndent() const
344 const Str& indent_ = getValueStr(XSLA_INDENT);
345 return (indent_ == (char*)"yes");
348 eFlag OutputDefinition::setDefaults(Sit S)
350 OutputMethod meth = getMethod();
351 assert( meth != OUTPUT_UNKNOWN );
352 char strYes[] = "yes", strNo[] = "no";
353 E( setItemStr(S, XSLA_ENCODING, "UTF-8", NULL, OUTPUT_PRECEDENCE_WEAKEST) );
358 E( setItemStr(S, XSLA_VERSION, "1.0", NULL, OUTPUT_PRECEDENCE_WEAKEST) );
359 E( setItemStr(S, XSLA_INDENT, strNo, NULL, OUTPUT_PRECEDENCE_WEAKEST) );
360 E( setItemStr(S, XSLA_MEDIA_TYPE, "text/xml", NULL, OUTPUT_PRECEDENCE_WEAKEST) );
361 E( setItemStr(S, XSLA_OMIT_XML_DECL, strNo, NULL, OUTPUT_PRECEDENCE_WEAKEST) );
365 E( setItemStr(S, XSLA_VERSION, "4.0", NULL, OUTPUT_PRECEDENCE_WEAKEST) );
366 E( setItemStr(S, XSLA_INDENT, strYes, NULL, OUTPUT_PRECEDENCE_WEAKEST) );
367 E( setItemStr(S, XSLA_MEDIA_TYPE, "text/html", NULL, OUTPUT_PRECEDENCE_WEAKEST) );
368 E( setItemStr(S, XSLA_OMIT_XML_DECL, strYes, NULL, OUTPUT_PRECEDENCE_WEAKEST) );
372 E( setItemStr(S, XSLA_INDENT, strNo, NULL, OUTPUT_PRECEDENCE_WEAKEST) );
373 E( setItemStr(S, XSLA_MEDIA_TYPE, "text/plain", NULL, OUTPUT_PRECEDENCE_WEAKEST) );
374 E( setItemStr(S, XSLA_OMIT_XML_DECL, strYes, NULL, OUTPUT_PRECEDENCE_WEAKEST) );
378 E( setItemStr(S, XSLA_VERSION, "1.0", NULL, OUTPUT_PRECEDENCE_WEAKEST) );
379 E( setItemStr(S, XSLA_INDENT, strYes, NULL, OUTPUT_PRECEDENCE_WEAKEST) );
380 E( setItemStr(S, XSLA_MEDIA_TYPE, "text/html", NULL, OUTPUT_PRECEDENCE_WEAKEST) );
381 E( setItemStr(S, XSLA_OMIT_XML_DECL, strYes, NULL, OUTPUT_PRECEDENCE_WEAKEST) );
387 void OutputDefinition::report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2)
389 S.message(type, code, arg1, arg2);
396 // PhysicalOutputLayerObj
400 #define sendStrEsc(SIT, STRING,ESCAPING) sendOut(SIT, (STRING), (STRING.length()), (ESCAPING))
401 #define sendStr(SIT, STRING) sendStrEsc(SIT, (STRING), ESCAPING_NONE)
402 #define sendLit(SIT, LITERAL) sendOut(SIT, (LITERAL), sizeof(LITERAL) - 1, ESCAPING_NONE)
403 // S is the situation (existing in each context indentEOL is called in)
404 #define indentEOL() {sendLit(S, "\n");}
405 #define indentSpace() {for (int i__ = 0; i__ < level; i__++) sendLit(S, " ");}
406 #define indentFull() {if (indent && after_markup) {indentEOL(); indentSpace();}}
407 #define ignoreTextMethod() {if (method == OUTPUT_TEXT) return OK; }
409 PhysicalOutputLayerObj::PhysicalOutputLayerObj(CDesc encodingCD_)
412 encodingCD = encodingCD_;
414 after_markup = FALSE; //pc
416 defaultNSWas = false;
419 PhysicalOutputLayerObj::~PhysicalOutputLayerObj()
423 eFlag PhysicalOutputLayerObj::setOptions(Sit S,
424 DataLine *targetDataLine_, OutputDefinition *outDef_)
426 targetDataLine = targetDataLine_;
428 method = outDef -> getMethod();
429 indent = outDef -> getIndent();
430 //enc = outDef -> getEncoding();
431 encoding = outDef -> getEncoding();
435 eFlag PhysicalOutputLayerObj::outputTrailingNewline (Sit S)
447 eFlag PhysicalOutputLayerObj::outputDone(Sit S)
453 Str _localName(Str fullname)
455 char *full = (char*)fullname;
456 char *colon = strchr(fullname, ':');
463 eFlag PhysicalOutputLayerObj::outputElementStart(Sit S,
465 const NamespaceStack& namespaces, const int namespace_index,
466 const StrStrList& atts,
469 //exit for text output method!!!
472 // begin output of start tag: output element name
473 if (!isNoEolHTMLTag(name) || (method != OUTPUT_HTML && method != OUTPUT_XHTML))
477 E( sendStr(S, name) );
479 // output namespace declarations
483 for (i = namespace_index; i < namespaces.number(); i++)
485 NamespaceStackObj * nm = namespaces[i];
486 prefix = &(nm -> prefix);
487 //prefix = &(namespaces[i] -> prefix);
488 //if (!namespaces.isHidden(*prefix))
490 // swallow hidden namespaces as well as the empty default
491 //namespace, if no default namespace was output recently
492 if (! nm -> hidden &&
493 (!(prefix -> isEmpty()) || !(nm -> uri.isEmpty()) || defaultNSWas))
495 defaultNSWas = prefix -> isEmpty();
497 sendLit(S, " xmlns");
498 if (!prefix -> isEmpty())
501 E( sendStr(S, *prefix) );
504 E( sendStrEsc(S, nm -> uri,
505 method == OUTPUT_HTML || method == OUTPUT_XHTML ?
506 ESCAPING_HTML_URI : ESCAPING_URI) );
513 for (i = 0; i < atts.number(); i++)
517 const EQName& attQName = atts[i] -> key;
518 if (attQName.hasPrefix())
520 E( sendStr(S, attQName.getPrefix()) );
523 const Str& localAttName = atts[i] -> key.getLocal();
524 E( sendStr(S, localAttName) );
526 sendOut(S, (char*)atts[i] -> key, atts[i] -> key.length(),
529 //boolean atts for html
530 if (method == OUTPUT_HTML && isBooleanHTMLAtt(atts[i]->key))
536 EscMode escapingMode =
537 ((method == OUTPUT_HTML || method == OUTPUT_XHTML) ?
538 ESCAPING_HTML_ATTR : ESCAPING_ATTR);
539 if ((method == OUTPUT_HTML || method == OUTPUT_XHTML) &&
540 isURI_HTMLAtt(_localName(atts[i]->key)))
542 escapingMode = ESCAPING_HTML_URI;
545 EscMode escapingMode = ESCAPING_ATTR;
546 if (method == OUTPUT_HTML || method == OUTPUT_XHTML)
548 if ( strchr(name, ':') )
550 escapingMode = ESCAPING_ATTR;
552 else if ( isURI_HTMLAtt(_localName(atts[i]->key)) )
554 escapingMode = ESCAPING_HTML_URI;
558 if (method == OUTPUT_HTML)
559 escapingMode = ESCAPING_HTML_ATTR;
563 E( sendStrEsc(S, atts[i] -> value, escapingMode));
569 after_markup = TRUE; //pc
578 if (method == OUTPUT_HTML || method == OUTPUT_XHTML)
580 if (!isEmptyHTMLTag(name))
586 else if (method == OUTPUT_HTML)
591 if (isNoEolHTMLTag(name))
592 after_markup = FALSE;
602 eFlag PhysicalOutputLayerObj::outputElementEnd(Sit S,
603 const Str& name, Bool isEmpty)
605 //exit for text output method!!!
613 E( sendStr(S, name) );
615 if (!isNoEolHTMLTag(name)) after_markup = TRUE; //pc
621 eFlag PhysicalOutputLayerObj::outputComment(Sit S, const Str& contents)
623 //exit for text output method!!!
628 const char *p = contents, *p_was = p;
629 int len = contents.length();
630 Bool trailingHyphen = len ? (contents[len - 1] == '-') : FALSE;
633 E( sendOutUntil(S, p, len - (p - p_was), ESCAPING_NONE, "--") );
643 after_markup = TRUE; //pc
648 eFlag PhysicalOutputLayerObj::outputCDataSection(Sit S, const Str& contents)
653 sendLit(S, contents);
657 const char *p = contents, *p_was = p;
661 sendLit(S, "<![CDATA[");
664 E( sendOutUntil(S, p,
665 contents.length() -(int)(p - p_was),
666 ESCAPING_NONE, "]]>") );
669 sendLit(S, "]]]]><![CDATA[>");
674 after_markup = TRUE; //pc
680 eFlag PhysicalOutputLayerObj::outputPI(Sit S, const Str& target, const Str& data)
682 //exit for text output method!!!
687 E( sendStr(S, target) );
689 E( sendStr(S, data) );
690 if (method == OUTPUT_HTML && !(target == (const char*)"xml"))
694 after_markup = TRUE; //pc
698 eFlag PhysicalOutputLayerObj::outputDTD(Sit S,
699 const Str& name, const Str& publicId, const Str& systemId)
701 //exit for text output method!!!
705 sendLit(S, "<!DOCTYPE ");
711 E( sendStr(S, name) );
712 if (!systemId.isEmpty())
714 if (!publicId.isEmpty())
716 sendLit(S, " PUBLIC \"");
717 E( sendStrEsc(S, publicId, ESCAPING_NONE) );
721 sendLit(S, " SYSTEM");
723 E( sendStrEsc(S, systemId, ESCAPING_URI) );
730 if (!publicId.isEmpty())
732 sendLit(S, " PUBLIC \"");
733 E( sendStrEsc(S, publicId, ESCAPING_NONE) );
736 if (!systemId.isEmpty())
738 if (publicId.isEmpty())
739 sendLit(S, " SYSTEM");
741 E( sendStrEsc(S, systemId, ESCAPING_URI) );
750 after_markup = TRUE; //pc
754 eFlag PhysicalOutputLayerObj::outputText(Sit S,
755 const Str& contents, Bool disableEsc,
763 E( sendStrEsc(S, contents, (disableEsc || inHTMLSpecial) ? ESCAPING_NONE : ESCAPING_LT_AMP) );
767 E( sendStrEsc(S, contents, (disableEsc || inHTMLSpecial) ? ESCAPING_NONE : ESCAPING_LT_AMP) );
771 E( sendStrEsc(S, contents, ESCAPING_NONE) );
774 after_markup = FALSE; //pc
779 eFlag PhysicalOutputLayerObj::flushBuffer(Sit S)
781 E( targetDataLine -> save(S, buffer, curr) );
786 int PhysicalOutputLayerObj::writeCharacterRef(char* dest, const char *src, EscMode escapeMode)
788 char *dest_was = dest;
789 if (escapeMode == ESCAPING_URI || escapeMode == ESCAPING_HTML_URI)
791 int i, iLimit = utf8SingleCharLength(src);
792 for (i = 0; i < iLimit; i++)
794 dest += sprintf(dest, "%%%02hhx", (unsigned char)src[i]);
796 return (int)(dest - dest_was);
799 return sprintf(dest, "&#%lu;", utf8CharCode(src));
802 // data is assumed null-terminated in the following
804 eFlag PhysicalOutputLayerObj::sendOutUntil(Sit S,
805 const char *& data, int length,
806 EscMode escapeMode, const char* stoppingText)
808 const char *p = strstr(data, stoppingText);
809 int sending = (p ? p - data : length);
810 E( sendOut(S, data, sending, escapeMode) );
817 #define minimum(a,b) (((a) < (b)) ? (a) : (b))
822 // This is the place where *all* actual character output and conversion work takes place. The
823 // individual characters are recoded and written into a buffer. When the buffer is full, it is
824 // sent to the appropriate dataline.
827 eFlag PhysicalOutputLayerObj::sendOut(Sit S,
828 const char* data, int length,
832 size_t srcCharLen, destCharLen;
835 size_t outleft, inleft;
838 while (count < length)
848 /* will escape < in URIs as < not the %xx way
850 case ESCAPING_HTML_URI:
853 writeCharacterRef(smallBuf, data, escapeMode),
859 case ESCAPING_HTML_URI:
861 case ESCAPING_LT_AMP:
863 E( sendLit(S, "<") );
873 case ESCAPING_HTML_URI:
875 case ESCAPING_LT_AMP:
877 if (method == OUTPUT_HTML || method == OUTPUT_XHTML)
879 E( sendLit(S, ">") );
889 /* will escape & in URIs as & not the %xx way
891 case ESCAPING_HTML_URI:
894 writeCharacterRef(smallBuf, data, escapeMode),
899 case ESCAPING_HTML_ATTR:
905 case ESCAPING_HTML_URI:
907 case ESCAPING_LT_AMP:
909 E( sendLit(S, "&") );
919 case ESCAPING_HTML_URI:
921 E( sendOut(S, smallBuf,
922 writeCharacterRef(smallBuf, data, escapeMode),
926 case ESCAPING_HTML_ATTR:
929 E( sendLit(S, """) );
941 case ESCAPING_HTML_URI:
943 case ESCAPING_HTML_ATTR:
945 E( sendOut(S, smallBuf,
946 writeCharacterRef(smallBuf, data, escapeMode),
957 case ESCAPING_HTML_URI:
959 E( sendOut(S, smallBuf,
960 writeCharacterRef(smallBuf, data, escapeMode),
968 // escape non-ASCII values in URIs
974 case ESCAPING_HTML_URI:
976 E( sendOut(S, smallBuf,
977 writeCharacterRef(smallBuf, data, escapeMode),
989 srcCharLen = utf8SingleCharLength(data);
990 assert(srcCharLen > 0);
991 // if encoding differs from utf-8 then recode
993 #ifdef SABLOT_DEBUGGER
996 debugger -> printOutput(data, srcCharLen);
1000 if (encodingCD == (void*)-1)
1002 memcpy(buffer + curr, data, srcCharLen);
1009 outbuf = buffer + curr;
1010 outleft = OUTPUT_BUFFER_SIZE - curr;
1011 inleft = srcCharLen;
1012 // getProcessor must be non-null here since encodingCD is
1013 S.recoder().conv(S, encodingCD, data, inleft, outbuf, outleft, result);
1014 // data is shifted automatically, set curr
1015 curr = outbuf - buffer;
1016 // check result, write a character code if
1017 //couldn't convert (unless ESCAPING_NONE)
1018 assert(result != ENC_EINVAL && result != ENC_E2BIG);
1019 // FIXME: in NT, must check differently
1020 if (result == ENC_EILSEQ)
1022 // unable to convert
1023 destCharLen = writeCharacterRef(smallBuf, data, escapeMode);
1024 //if (escapeMode == ESCAPING_NONE)
1025 if (method == OUTPUT_TEXT)
1026 Err1(S, E1_BAD_CHAR_IN_ENC, smallBuf)
1029 E( sendOut(S, smallBuf, destCharLen, ESCAPING_NONE) );
1041 // send the buffer if over a threshold
1042 if (curr > OUTPUT_BUFFER_LIMIT)
1045 count += srcCharLen;
1046 // curr already got shifted in all cases
1053 eFlag PhysicalOutputLayerObj::setMethodByDefault(Sit S, OutputMethod method_)
1056 assert(method == OUTPUT_UNKNOWN);
1057 switch( method = method_ )
1060 q.setLocal("xml"); break;
1062 q.setLocal("html"); break;
1064 assert(!"PhysicalOutputLayerObj::setMethod()");
1066 E( NZ(outDef) -> setItemEQName(S, XSLA_METHOD, q, NULL, OUTPUT_PRECEDENCE_STRONGEST) );
1067 E( outDef -> setDefaults(S) );
1071 void PhysicalOutputLayerObj::report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2)
1073 S.message(type, code, arg1, arg2);
1084 eFlag FrontMatter::appendConstruct(Sit S,
1085 FrontMatterKind kind, const Str& string1,
1086 const Str& string2, Bool disableEsc)
1088 FrontMatterItem* item;
1090 M( S, item = new FrontMatterItem ); // GP: OK
1091 item -> kind = kind;
1092 item -> string1 = string1;
1093 item -> string2 = string2;
1094 item -> disableEsc = disableEsc;
1099 void FrontMatter::report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2)
1101 S.message(type, code, arg1, arg2);
1110 OutputDocument::~OutputDocument()
1112 if (outputter) delete outputter;
1113 if (def) delete def;
1116 eFlag OutputDocument::finish(Sit S)
1118 if (state == OUTDOC_ACTIVE)
1120 E( NZ(outputter) -> eventTrailingNewline(S) );
1121 E( NZ(outputter) -> eventEndOutput(S) );
1122 setState(OUTDOC_FINISHED);
1127 OutputterObj* OutputDocument::setOutputter(OutputterObj* new_)
1129 if (outputter) delete outputter;
1130 return outputter = new_;
1140 Str* OutputterObj::nameForSAX(Sit S, const EQName& q)
1143 if (mySAXOutputType == SAXOUTPUT_COPY_TREE ||
1144 mySAXOutputType == SAXOUTPUT_INT_PHYSICAL)
1146 if (q.getUri().isEmpty())
1147 return new Str(q.getLocal());
1149 temp += THE_NAMESPACE_SEPARATOR;
1150 temp += q.getLocal();
1151 temp += THE_NAMESPACE_SEPARATOR;
1152 temp += q.getPrefix();
1153 return new Str(temp);
1163 OutputterObj::OutputterObj()
1165 encodingCD = (CDesc) -1;
1166 outputEscaping = TRUE;
1169 mySAXHandler = NULL;
1170 mySAXOutputType = SAXOUTPUT_NONE;
1171 method = OUTPUT_UNKNOWN;
1172 noElementYet = TRUE;
1175 // to recognize the first HEAD element
1178 OutputterObj::~OutputterObj()
1180 history.freeall(FALSE);
1181 front.freeall(FALSE);
1182 currNamespaces.freeall(FALSE);
1186 eFlag OutputterObj::setOptions(Sit S,
1187 DataLine *targetDataLine_, OutputDefinition *outDef_)
1190 outDef = NZ(outDef_);
1191 method = outDef -> getMethod(); //_PH_
1192 if (method != OUTPUT_UNKNOWN)
1193 E( outDef -> setDefaults(S) );
1195 if (S.getProcessor())
1197 encoding = S.getProcessor() -> getHardEncoding();
1198 if ( !encoding.isEmpty() )
1199 outDef -> setItemStr(S, XSLA_ENCODING, encoding, NULL,
1200 OUTPUT_PRECEDENCE_STRONGEST);
1204 if (encoding.isEmpty())
1205 encoding = outDef -> getValueStr(XSLA_ENCODING);
1206 if (!encoding.isEmpty() && !encoding.eqNoCase("utf-8"))
1208 // set the conversion descriptor
1209 if (S.getProcessor())
1211 E( S.recoder().openFromUTF8(S,
1212 encoding, encodingCD) );
1215 encodingCD = (ConvInfo*)-1;
1216 if (encodingCD == (void*)-1)
1218 Warn1(S, W1_UNSUPP_OUT_ENCODING, encoding);
1220 E( outDef -> setItemStr(S, XSLA_ENCODING, encoding,
1221 NULL, OUTPUT_PRECEDENCE_STRONGEST) );
1225 if (!encoding.isEmpty())
1226 E( outDef -> setItemStr(S, XSLA_ENCODING, encoding,
1227 NULL, OUTPUT_PRECEDENCE_WEAKEST) );
1229 if (targetDataLine_)
1231 M( S, physical = new PhysicalOutputLayerObj(encodingCD) );
1232 // GP: OK, OutputterObj gets disposed of in cleanupAfterRun
1233 E( physical -> setOptions(S, targetDataLine_, outDef_) );
1239 eFlag OutputterObj::setOptionsSAX(Sit S,
1240 SAXHandler *streaming_, void* userData_, SAXOutputType saxout_)
1242 mySAXHandler = streaming_;
1243 mySAXUserData = userData_;
1244 mySAXOutputType = saxout_;
1248 eFlag OutputterObj::reportXMLDeclIfMust(Sit S)
1250 if (!physical || method == OUTPUT_UNKNOWN ||
1251 outDef -> getValueStr(XSLA_OMIT_XML_DECL) == (const char*)"yes")
1253 DStr declText = "version=\"";
1254 declText += outDef -> getValueStr(XSLA_VERSION);
1255 declText += "\" encoding=\"";
1256 declText += outDef -> getValueStr(XSLA_ENCODING);
1258 const Str &standaloneText = outDef -> getValueStr(XSLA_STANDALONE);
1259 if (!standaloneText.isEmpty())
1261 declText += " standalone=\"";
1262 declText += standaloneText;
1265 E( physical -> outputPI(S, Str("xml"), declText) );
1269 eFlag OutputterObj::reportDTDIfMust(Sit S, const EQName& docElementName)
1270 // to be called only after the output method is determined
1272 assert(method != OUTPUT_TEXT);
1276 DTSystem = outDef -> getValueStr(XSLA_DOCTYPE_SYSTEM),
1277 DTPublic = outDef -> getValueStr(XSLA_DOCTYPE_PUBLIC);
1283 writeDTD = !DTSystem.isEmpty();
1286 writeDTD = !DTSystem.isEmpty() || !DTPublic.isEmpty();
1292 delayedDTD = writeDTD;
1298 docElementName.getname(fullName);
1306 eFlag OutputterObj::reportFront(Sit S)
1308 assert(method != OUTPUT_UNKNOWN);
1309 int i, frontCount = front.number();
1310 FrontMatterItem *item;
1311 for(i = 0; i < frontCount; i++)
1314 switch(item -> kind)
1318 if (item -> disableEsc)
1319 E( eventDisableEscapingForNext(S) );
1320 E( eventData(S, item -> string1) );
1324 E( eventPIStart(S, item -> string1) );
1325 E( eventData(S, item -> string2) );
1330 E( eventCommentStart(S) );
1331 E( eventData(S, item -> string1) );
1332 E( eventCommentEnd(S) );
1340 eFlag OutputterObj::eventBeginOutput(Sit S)
1343 pushLevel(dummy); //experimental
1344 method = outDef ? outDef -> getMethod() : OUTPUT_UNKNOWN;
1347 //??JP??both physical & method !=...
1348 //duplicit with the same in reportXMLDeclIfMust
1349 if (method != OUTPUT_UNKNOWN)
1350 E( reportXMLDeclIfMust(S) );
1352 // initialize the SAX interface
1353 IF_SAX1( startDocument );
1354 state = STATE_OUTSIDE;
1358 eFlag OutputterObj::eventBeginSubtree(Sit S)
1361 pushLevel(dummy); //experimntal
1362 method = outDef -> getMethod();
1365 // method = outDef -> getMethod();
1367 // initialize the SAX interface
1368 IF_SAX1( startDocument );
1369 state = STATE_OUTSIDE;
1374 eFlag OutputterObj::eventElementStart(Sit S, const EQName& name)
1378 noElementYet = FALSE;
1381 if (method == OUTPUT_UNKNOWN)
1383 if (name.getUri().isEmpty() && name.getLocal().eqNoCase("html"))
1384 method = OUTPUT_HTML;
1386 method = OUTPUT_XML;
1387 E( physical -> setMethodByDefault(S, method) );
1388 E( reportXMLDeclIfMust(S) );
1389 E( reportFront(S) );//??JP??sax
1391 // If this is an included stylesheet, output method cd be TEXT here
1392 if (method != OUTPUT_TEXT) {
1393 E( reportDTDIfMust( S, name ) );//??JP??sax
1400 case STATE_IN_MARKUP:
1401 case STATE_IN_ELEMENT:
1403 // reportStartTag also sends the event to SAX
1404 E( reportStartTag(S, NONEMPTY_ELEMENT) );
1405 E( reportCurrData(S) );
1407 // this sets state to STATE_IN_MARKUP
1410 case STATE_IN_COMMENT:
1412 case STATE_IN_ATTRIBUTE:
1413 Err( S, E_ELEM_IN_COMMENT_PI );
1415 assert(!"eventElementStart");
1418 // determine whether we're in a HEAD html element so a META tag
1419 // needs to be added
1424 eFlag OutputterObj::throwInMeta(Sit S)
1428 if ( S.hasFlag(SAB_DISABLE_ADDING_META) ) return OK;
1430 if (physical || mySAXHandler)
1432 Str metaName("meta");
1433 Str httpEquiv("http-equiv");
1434 Str contentType("Content-Type");
1435 Str content("content");
1437 NZ(outDef) -> getValueStr(XSLA_MEDIA_TYPE) + "; charset=" +
1438 outDef -> getValueStr(XSLA_ENCODING);
1441 StrStrList metaAtts;
1445 //httpEquivName.setLocal("http-equiv");
1446 //contentName.setLocal("content");
1447 metaAtts.appendConstruct(httpEquiv, contentType);
1448 metaAtts.appendConstruct(content, contentValue);
1449 E( physical -> outputElementStart(S, metaName, currNamespaces,
1450 getFirstOwnNS(), metaAtts, TRUE) );
1451 E( physical -> outputElementEnd(S, metaName, TRUE) );
1452 metaAtts.freeall(FALSE);
1457 saxAtts[0] = httpEquiv;
1458 saxAtts[1] = contentType;
1459 saxAtts[2] = content;
1460 saxAtts[3] = (char *) contentValue;
1462 mySAXHandler->startElement(mySAXUserData, S.getProcessor(),
1464 (const char**) saxAtts);
1465 mySAXHandler->endElement(mySAXUserData, S.getProcessor(),
1469 state = STATE_IN_ELEMENT;//??JP?? why to change state ?
1477 eFlag OutputterObj::eventElementEnd(Sit S, const EQName& name)
1479 assert(!(physical && mySAXOutputType == SAXOUTPUT_INT_PHYSICAL));
1481 // if (S.getProcessor())
1482 // temp = S.getProcessor() -> getAliasedName(name,
1484 // mySAXOutputType == SAXOUTPUT_INT_PHYSICAL);
1485 //else name.getname(temp);
1489 case STATE_IN_MARKUP:
1490 E( reportStartTag(S, EMPTY_ELEMENT) );
1492 case STATE_IN_ELEMENT:
1494 E( reportCurrData(S) );
1498 name.getname(physName);
1499 physical -> outputElementEnd(S, physName, NONEMPTY_ELEMENT );
1503 assert(!"eventElementEnd");
1506 // send the event to SAX
1507 switch(mySAXOutputType)
1509 case SAXOUTPUT_COPY_TREE:
1510 case SAXOUTPUT_INT_PHYSICAL:
1512 GP( Str ) theSAXname = nameForSAX(S, name);
1513 IF_SAX2( endElement, (const char*) *theSAXname );
1515 // report namespace scope ends
1516 //while (currNamespaces.number() > getFirstOwnNS())
1517 for (int ii = currNamespaces.number() - 1; ii >= getFirstOwnNS(); ii--)
1519 IF_SAX2( endNamespace, currNamespaces[ii] -> prefix );
1524 case SAXOUTPUT_AS_PHYSICAL:
1527 name.getname(physName);
1528 IF_SAX2( endElement, (const char*) physName );
1529 // report namespace scope ends
1531 //while (currNamespaces.number() > getFirstOwnNS())
1532 for (int ii = currNamespaces.number() - 1; ii >= getFirstOwnNS(); ii--)
1534 prefix = &(currNamespaces[ii] -> prefix);
1535 if (! currNamespaces.isHidden(*prefix))
1536 IF_SAX2( endNamespace, currNamespaces[ii] -> prefix );
1540 case SAXOUTPUT_NONE: break;
1542 assert(!"eventElementEnd");
1545 //remove our namespaces
1546 while (currNamespaces.number() > getFirstOwnNS())
1547 currNamespaces.freelast(FALSE);
1549 // pop one history level
1550 history.freelast(FALSE);
1551 if (getLevel()) //experimental
1552 state = STATE_IN_ELEMENT;
1554 state = STATE_OUTSIDE;
1560 eFlag OutputterObj::eventAttributeStart(Sit S, const EQName& name)
1563 name.getname(fullName);
1566 case STATE_IN_MARKUP:
1568 state = STATE_IN_ATTRIBUTE;
1571 case STATE_IN_ELEMENT:
1573 Err1(S, E1_ATTRIBUTE_TOO_LATE, fullName);
1578 Err1(S, E1_ATTRIBUTE_OUTSIDE, fullName);
1582 assert(!"eventAttributeStart");
1588 eFlag OutputterObj::eventAttributeEnd(Sit S)
1590 assert(state == STATE_IN_ATTRIBUTE);
1592 int currAttNameNdx = currAtts.findNdx(currAttName);
1593 if (currAttNameNdx != -1)
1594 currAtts[currAttNameNdx] -> value = currData;
1596 currAtts.appendConstruct(currAttName, currData);
1598 state = STATE_IN_MARKUP;
1603 eFlag OutputterObj::eventCommentStart(Sit S)
1607 case STATE_IN_MARKUP:
1608 E( reportStartTag(S, NONEMPTY_ELEMENT) );
1611 case STATE_IN_ELEMENT:
1613 E( reportCurrData(S) );
1614 state = STATE_IN_COMMENT;
1617 assert(!"eventCommentStart");
1622 eFlag OutputterObj::eventCommentEnd(Sit S)
1624 assert(state == STATE_IN_COMMENT);
1625 if (physical && method == OUTPUT_UNKNOWN)
1626 E( front.appendConstruct(S, FM_COMMENT, currData,
1627 ""/**theEmptyString*/, FALSE) )
1630 IF_PH2( outputComment, currData );
1631 IF_SAX2( comment, currData );
1634 state = (getLevel() ? STATE_IN_ELEMENT : STATE_OUTSIDE); //experimental
1638 eFlag OutputterObj::eventPIStart(Sit S, const Str& name)
1642 case STATE_IN_MARKUP:
1643 E( reportStartTag(S, NONEMPTY_ELEMENT) );
1645 case STATE_IN_ELEMENT:
1648 E( reportCurrData(S) );
1649 state = STATE_IN_PI;
1653 assert(!"eventPIStart");
1658 eFlag OutputterObj::eventPIEnd(Sit S)
1660 assert(state == STATE_IN_PI);
1663 if ( strstr((char*)currData, "?>") )
1664 Err(S, E_INVALID_DATA_IN_PI);
1666 if (physical && method == OUTPUT_UNKNOWN)
1667 E( front.appendConstruct(S, FM_PI, currPIName, currData, FALSE) )
1670 IF_PH3( outputPI, currPIName, currData );
1671 IF_SAX3( processingInstruction, currPIName, currData );
1675 state = (getLevel() ? STATE_IN_ELEMENT : STATE_OUTSIDE);
1679 eFlag OutputterObj::eventNamespace(Sit S, const Str& prefix, const Str& uri,
1682 assert(state == STATE_IN_MARKUP);
1683 // GP: OK, not allocated
1685 int existing_ndx = currNamespaces.findNum(prefix);
1686 const Str *existing_namespace = (
1687 existing_ndx == -1 ? NULL : &(currNamespaces[existing_ndx] -> uri));
1688 //explanation: if we found previously inserted namespace, we have
1689 //to add new definition to override it with one exception. Two
1690 //namespaces with the same prefix may be added (e.g. for
1691 //xsl:element insrtuction) in this case (existing_ndx >=
1692 //getFirstOwnNS()) we need override former definition in place.
1695 if (uri == theXSLTNamespace)
1697 //we need to reveal the xslt namespace if it is aliased
1698 Processor *proc = S.getProcessor();
1702 E( proc -> prefixIsAliasTarget(S, prefix, aliased) );
1703 hidden = hidden && ! aliased;
1708 if (!existing_namespace)
1710 //if the namespace doesn't exist yet, we add it
1711 currNamespaces.appendConstruct(prefix, uri, hidden);
1715 Bool exIsHidden = currNamespaces[existing_ndx]->hidden;
1716 // the following condition was asserted here for some reason
1717 if (!(*existing_namespace == uri))
1719 if (existing_ndx >= getFirstOwnNS())
1721 currNamespaces[existing_ndx] -> uri = uri;
1722 currNamespaces[existing_ndx] -> hidden = hidden;
1726 currNamespaces.appendConstruct(prefix, uri, hidden);
1729 //may be we found excluded one, but in current subtree
1731 else if (exIsHidden && !hidden)
1733 currNamespaces.appendConstruct(prefix, uri, hidden);
1739 eFlag OutputterObj::eventDisableEscapingForNext(Sit S)
1741 if (method != OUTPUT_TEXT)
1745 case STATE_IN_ATTRIBUTE:
1747 case STATE_IN_COMMENT:
1748 Warn(S, W_DISABLE_OUTPUT_ESC); break;
1750 outputEscaping = FALSE;
1756 eFlag OutputterObj::eventData(Sit S, const Str& data, Bool hardCData /* = FALSE */)
1758 if (physical && method == OUTPUT_UNKNOWN && state == STATE_OUTSIDE)
1760 E( front.appendConstruct(S, FM_TEXT, data,
1761 "" /**theEmptyString*/, !outputEscaping) );
1762 if (!isAllWhite((const char*) data))
1764 E( physical -> setMethodByDefault(S, method = OUTPUT_XML) );
1765 E( reportXMLDeclIfMust(S) );
1766 E( reportFront(S) );
1773 case STATE_IN_MARKUP:
1774 E( reportStartTag(S, NONEMPTY_ELEMENT) );
1776 case STATE_IN_ELEMENT:
1778 { // this is a text node
1779 if (!(getFlags() & CDATA_SECTION) && !hardCData)
1781 int htmlScriptOrStyle = ( getFlags() & HTML_SCRIPT_OR_STYLE );
1784 E( physical -> outputText(S, data, !outputEscaping,
1785 htmlScriptOrStyle) );
1787 // reset outputEscaping to default after use
1788 // even if we just save a part of cdata section
1789 outputEscaping = TRUE;
1790 state = getLevel() ? STATE_IN_ELEMENT : STATE_OUTSIDE;
1792 case STATE_IN_COMMENT:
1794 case STATE_IN_ATTRIBUTE:
1799 assert(!"eventData()");
1804 eFlag OutputterObj::eventCDataSection(Sit S, const Str& data)
1808 case STATE_IN_MARKUP:
1809 E( reportStartTag(S, NONEMPTY_ELEMENT) );
1812 case STATE_IN_ELEMENT:
1814 E( reportCurrData(S) );
1815 E( eventData(S, data, /* hardCData = */ TRUE) );
1816 E( reportCurrData(S, /* hardCData = */ TRUE) );
1819 assert(!"eventCDataSection()");
1824 eFlag OutputterObj::eventEndOutput(Sit S)
1826 assert(state == STATE_OUTSIDE);
1827 E( reportCurrData(S) );
1828 if (physical && method == OUTPUT_UNKNOWN)
1830 E( physical -> setMethodByDefault(S, method = OUTPUT_XML) );
1831 E( reportXMLDeclIfMust(S) );
1832 E( reportFront(S) );
1834 IF_PH1( outputDone );
1835 IF_SAX1( endDocument );
1838 //pop fake history item
1839 history.freelast(FALSE);
1844 eFlag OutputterObj::eventTrailingNewline(Sit S)
1846 assert(state == STATE_OUTSIDE);
1849 E(physical -> outputTrailingNewline(S))
1854 eFlag OutputterObj::reportCurrData(Sit S, Bool hardCData /* = FALSE */)
1856 if (currData.isEmpty())
1861 case STATE_IN_MARKUP:
1862 case STATE_IN_ELEMENT:
1864 if (getFlags() & CDATA_SECTION || hardCData)
1866 // we might now call the SAX startCData handler (if there was one)
1867 IF_SAX3( characters, currData, currData.length() );
1868 IF_PH2( outputCDataSection, currData );
1869 // we might call the SAX endCData handler
1873 // the text had been output to physical in parts
1874 IF_SAX3( characters, currData, currData.length());
1878 assert(!"reportCurrData()");
1886 GP: if this function is modified, care must be taken about the guarded
1890 eFlag OutputterObj::reportStartTag(Sit S, Bool isEmpty)
1892 assert(!(physical && mySAXOutputType == SAXOUTPUT_INT_PHYSICAL));
1893 // FIXME: couldn't improve reportStartTag from GP point of view?
1894 if (state == STATE_OUTSIDE || currElement.isEmpty())
1897 int doThrowMeta = method == OUTPUT_HTML && noHeadYet &&
1898 currElement.getUri().isEmpty() && currElement.getLocal().eqNoCase("head");
1900 //get attr aliased names
1901 StrStrList attAliased;
1902 // the temporary string is a workaround for VisualAge on AIX
1907 Bool intPhys = mySAXOutputType == SAXOUTPUT_INT_PHYSICAL;
1909 if (physical || (mySAXHandler && (mySAXOutputType == SAXOUTPUT_AS_PHYSICAL)))
1911 //if (S.getProcessor())
1912 //temp = S.getProcessor() -> getAliasedName(currElement,
1913 // currNamespaces, intPhys);
1915 //currElement.getname(temp);
1916 currElement.getname(physName);
1918 for (i = 0; i < currAtts.number(); i++)
1921 //if (S.getProcessor())
1922 // aliname = S.getProcessor() -> getAliasedName(currAtts[i] -> key,
1926 // currAtts[i] -> key.getname(aliname);
1927 currAtts[i] -> key.getname(aliname);
1928 attAliased.appendConstruct(aliname, currAtts[i] -> value);
1935 DTSystem = outDef -> getValueStr(XSLA_DOCTYPE_SYSTEM),
1936 DTPublic = outDef -> getValueStr(XSLA_DOCTYPE_PUBLIC);
1937 E( physical -> outputDTD( S, physName, DTPublic, DTSystem) );
1941 E( physical -> outputElementStart(S, physName, currNamespaces,
1942 getFirstOwnNS(), attAliased,
1943 isEmpty && !doThrowMeta) );
1949 const char** attsTable;
1950 GPA( ConstCharP ) attsArr = attsTable = new const char*[(currAtts.number() * 2) + 1];
1951 // GP: the allocations are OK: no exit routes
1953 PList<Str*> stringsForDeletion;
1954 attsTable[currAtts.number() * 2] = NULL;
1956 switch(mySAXOutputType)
1958 case SAXOUTPUT_COPY_TREE:
1959 case SAXOUTPUT_INT_PHYSICAL:
1961 // report only the new namespaces
1963 for (i = getFirstOwnNS(); i < currNamespaces.number(); i++)
1965 prefix = &(currNamespaces[i] -> prefix);
1968 IF_INT_SAX4( startNamespace2, currNamespaces[i] -> prefix,
1969 currNamespaces[i] -> uri,
1970 currNamespaces.isHidden(*prefix) );
1973 IF_SAX3( startNamespace, currNamespaces[i] -> prefix,
1974 currNamespaces[i] -> uri );
1976 // create the attribute table
1977 for (i = 0; i < currAtts.number(); i++)
1979 Str *expatName = nameForSAX(S, currAtts[i] -> key);
1980 stringsForDeletion.append(expatName);
1981 attsTable[i * 2] = *expatName;
1982 attsTable[(i * 2) + 1] = currAtts[i] -> value;
1984 Str* theSAXname = nameForSAX(S, currElement);
1985 stringsForDeletion.append(theSAXname);
1986 IF_SAX3(startElement, *theSAXname, attsTable);
1987 stringsForDeletion.freeall(FALSE);
1990 case SAXOUTPUT_AS_PHYSICAL:
1991 // report only the new not hidden namespaces
1993 for (i = getFirstOwnNS(); i < currNamespaces.number(); i++)
1995 prefix = &(currNamespaces[i] -> prefix);
1996 if (! currNamespaces.isHidden(*prefix))
1997 IF_SAX3( startNamespace, currNamespaces[i] -> prefix,
1998 currNamespaces[i] -> uri );
2000 // create the attribute table
2001 for (i = 0; i < currAtts.number(); i++)
2003 attsTable[i * 2] = (char *)attAliased[i] -> key;
2004 attsTable[(i * 2) + 1] = (char *)attAliased[i] -> value;
2007 IF_SAX3(startElement, physName, attsTable);
2009 case SAXOUTPUT_NONE:
2010 assert(!"saxoutput == NONE");
2012 assert(!"eventElementEnd");
2014 //attsTable.delArray();
2017 if (physical || (mySAXHandler && mySAXOutputType == SAXOUTPUT_AS_PHYSICAL))
2019 attAliased.freeall(FALSE);
2024 result = throwInMeta(S);
2025 //__PH__ close head if needed
2028 E( physical ->outputElementEnd(S, physName, FALSE) );
2033 currElement.empty();
2034 currAtts.freeall(FALSE);
2039 void OutputterObj::pushLevel(const EQName& name)
2042 GP( OutputHistoryItem ) newItem = new OutputHistoryItem;
2043 if (history.number())
2045 *newItem = *(history.last());
2046 //next line is speed optimalization (very few)
2047 (*newItem).useDocument = (*(history.last())).document;
2051 (*newItem).flags = 0;
2052 (*newItem).useDocument = NULL;
2054 //definition is used for multiple document output
2055 (*newItem).document = NULL; //in any case
2058 if (outDef -> askEQNameList(XSLA_CDATA_SECT_ELEMS, name))
2059 (*newItem).flags |= CDATA_SECTION;
2061 (*newItem).flags &= ~CDATA_SECTION;
2063 //style and script for html
2064 if ( (method == OUTPUT_HTML && name.getUri() == "") &&
2065 isHTMLNoEscapeTag(name.getLocal()) )
2067 (*newItem).flags |= HTML_SCRIPT_OR_STYLE;
2071 (*newItem).flags &= ~HTML_SCRIPT_OR_STYLE;
2074 (*newItem).firstOwnNS = currNamespaces.number();
2075 history.append(newItem.keep());
2076 state = STATE_IN_MARKUP;
2079 void OutputterObj::report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2)
2081 S.message(type, code, arg1, arg2);
2084 eFlag OutputterObj::setDocumentForLevel(Sit S, OutputDocument *doc)
2086 if (history.number())
2087 (*(history.last())).document = doc;
2091 OutputDocument* OutputterObj::getDocumentForLevel(Bool forElement)
2093 if (history.number())
2094 return forElement ? (*(history.last())).useDocument :
2095 (*(history.last())).document;