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): Tim Crook <tcrook@accelio.com>
19 * Christian Lefebvre <christian.lefebvre@atosorigin.com>
21 * Alternatively, the contents of this file may be used under the
22 * terms of the GNU General Public License Version 2 or later (the
23 * "GPL"), in which case the provisions of the GPL are applicable
24 * instead of those above. If you wish to allow use of your
25 * version of this file only under the terms of the GPL and not to
26 * allow others to use your version of this file under the MPL,
27 * indicate your decision by deleting the provisions above and
28 * replace them with the notice and other provisions required by
29 * the GPL. If you do not delete the provisions above, a recipient
30 * may use your version of this file under either the MPL or the
53 SAXHandlerInternal TreeConstructer::myHandlerRecord =
67 TreeConstructer::TreeConstructer(Sit S_)
74 inSAXForAWhile = FALSE;
78 TreeConstructer::~TreeConstructer()
83 eFlag TreeConstructer::parseDataLineUsingGivenExpat(Sit S,
84 Tree *t, DataLine *d, XML_Parser theParser_)
88 theParser = theParser_;
90 S.setCurrFile(d -> fullUri);
91 E( feedDocumentToParser(S, this) );
92 E( t -> parseFinished(S) );
95 t -> stripped += t -> getRoot().strip();
96 E( t -> aliases().checkRedefinitions(S, *t) );
97 E( t -> attSets().checkRedefinitions(S) );
103 eFlag TreeConstructer::parseDataLineUsingExpat(Sit S,
104 Tree *t, DataLine *d,
105 char *base_ /*=NULL*/)
107 theParser = XML_ParserCreateNS(NULL, THE_NAMESPACE_SEPARATOR);
110 // XML_UseParserAsHandlerArg(parser);
111 XML_SetElementHandler(theParser,
114 XML_SetCharacterDataHandler(theParser,
116 XML_SetNamespaceDeclHandler(theParser,
119 XML_SetCommentHandler(theParser,
121 XML_SetProcessingInstructionHandler(theParser,
124 // the unknown encoding handler is no more used:
125 // XML_SetUnknownEncodingHandler(theParser,
126 // tcUnknownEncoding,
129 XML_SetExternalEntityRefHandler(theParser,
130 tcExternalEntityRef);
131 XML_SetEntityDeclHandler(theParser, tcEntityDecl);
134 XML_SetUserData(theParser, this);
135 if (S.getProcessor())
136 XML_SetBase(theParser, S.getProcessor() -> findBaseURI(S, t ->getURI()));
138 XML_SetBase(theParser, base_);
140 // wasn't this done before?
141 XML_SetParamEntityParsing(theParser, XML_PARAM_ENTITY_PARSING_ALWAYS);
143 //we want to get all info (including prefixes)
144 #ifdef EXPAT_SUPPORTS_TRIPLETS
145 XML_SetReturnNSTriplet(theParser, 1);
148 eFlag eCode = parseDataLineUsingGivenExpat(S, t, d, theParser);
150 XML_ParserFree(theParser);
156 eFlag TreeConstructer::parseUsingSAX(Sit S, Tree *t, OutputterObj& source,
161 // register the handler with the outputter
162 E( source.setOptionsSAX(S, (SAXHandler*)&myHandlerRecord, this, ot) );
163 E( source.eventBeginOutput(S) );
167 eFlag TreeConstructer::parseUsingSAXForAWhile(Sit S, OutputterObj& source,
169 Bool resetNamespaces,
172 // it's assumed that this is a tree constructer over a dataline
175 assert(theTree && theDataLine);
176 inSAXForAWhile = TRUE;
180 E( theTree -> pushPendingNS(S, srcTree, swallowNS) );
182 // register the handler with the outputter
183 E( source.setOptionsSAX(S, (SAXHandler*)&myHandlerRecord, this, SAXOUTPUT_COPY_TREE) );
184 E( source.eventBeginOutput(S) );
188 eFlag TreeConstructer::parseUsingSAXForAWhileDone(Sit S, OutputterObj& source,
189 Bool resetNamespaces)
191 E( source.eventEndOutput(S) );
192 inSAXForAWhile = FALSE;
195 E( theTree -> popPendingNS(S) );
200 int TreeConstructer::getCurrentLineNumber() const
202 if (this -> inSAXForAWhile)
204 return this -> S.getCurrSAXLine();
208 return XML_GetCurrentLineNumber(theParser);
211 return theLineNumber;
215 eFlag TreeConstructer::getDocEncoding(Sit S, const char *buf, Str& theEncoding, TreeConstructer *this_)
216 // assumes the parse buffer null-terminated
218 // copy the unsigned shorts out of the string to avoid misalignment
219 unsigned short bom_part1, bom_part2;
220 memcpy (&bom_part1, buf, sizeof(unsigned short));
225 theEncoding = "UTF-16";
229 // no byte order mark!
230 memcpy (&bom_part2, buf+1, sizeof(unsigned short));
231 if ((bom_part2 == 0x003f) ||
232 (bom_part2 == 0x3f00))
233 theEncoding = "UTF-16";
235 this_ -> Warn(S, W_BAD_START);
238 memcpy (&bom_part2, buf+1, sizeof(unsigned short));
239 if ((bom_part2 == 0x003c) ||
240 (bom_part2 == 0x3c00))
241 theEncoding = "ISO-10646-UCS-4";
243 this_ -> Warn(S, W_BAD_START);
247 // look for "<?xml " to distinguish from "<?xml-stylesheet"
248 // or any other similar processing instructions
250 if (buf[0] == '<' && buf[1] == '?' && buf[2] == 'x'
251 && buf[3] == 'm' && buf[4] == 'l' && buf[5] == ' ')
254 p = strpbrk(p + 2,"=?");
255 while (! found && p && *p == '=')
257 //now find the pseudo-attribute name
258 const char *beg = p - 1;
259 while ( isWhite(*beg) ) beg--;
260 while ( (!isWhite(*beg)) && *beg != '?') beg--;
261 if ( strncmp(beg + 1, "encoding", 8) )
262 p = strpbrk(p + 1, "=?");
268 const char *q = strpbrk(p + 1, "?\'\"");
269 if (q && *q != '?' && *q == *p)
271 theEncoding.nset(p + 1, q - p - 1);
277 if (! found) theEncoding = "UTF-8";
285 eFlag TreeConstructer::feedDocumentToParser(Sit S, void* constructer)
287 TreeConstructer *this_ =
288 (TreeConstructer*) constructer;
289 //char convBuffer[PARSE_CONV_BUFSIZE];
290 //char rawBuffer[PARSE_BUFSIZE + 1];
292 char *convBuffer, *rawBuffer;
293 GPA( GChar ) convAux = convBuffer = new char[PARSE_CONV_BUFSIZE];
294 GPA( GChar ) rawAux = rawBuffer = new char[PARSE_BUFSIZE + 1];
296 char *outbuf = (char *) convBuffer;
297 const char *inbuf = (char *) rawBuffer;
299 Bool quit = FALSE, firstTime = TRUE;
300 Bool mustConvert = FALSE, haveReadAll = FALSE;
301 int res = 0, bytes = 0;
302 size_t inleft = 0, outleft = 0;
303 EncResult convResult = ENC_OK;
304 CDesc cd = (CDesc) -1;
305 // seems to be useless here
307 // EncHandler *recoder = NZ(S.getProcessor()) -> getEncHandler(&recoderUD);
312 XML_Parser parser = NZ( this_ -> theParser );
314 // GP: tree constructer does get killed on error
315 // callers are Processor::parse (stack variable) and ext ent handler (disposes)
317 // this is to add the 'xml' namespace declarations
319 tcStartNamespace(constructer, "xml", theXMLNamespace);
323 // char *buf = (char*) XML_GetBuffer(parser, PARSE_BUFSIZE + 1);
328 // just get the next block of data
329 bytes = this_ -> theDataLine -> get(S, rawBuffer, PARSE_BUFSIZE);
330 haveReadAll = (bytes < PARSE_BUFSIZE);
336 // buffer ended with an incomplete sequence
338 memmove(rawBuffer, inbuf, inleft);
339 // get the rest from dataline
340 bytes = this_ -> theDataLine -> get(S, rawBuffer + inleft, PARSE_BUFSIZE - inleft);
341 haveReadAll = (bytes < PARSE_BUFSIZE - (int) inleft);
347 // the converted text was too big to fit in convBuffer
348 // don't get more, just convert from input buffer
349 // not changing haveReadAll, inbuf or inleft
352 assert(!"feedDocumentToParser");
355 // the test for bytes==-1 is superfluous but just in case
356 if (bytes == -1 || S.isError())
358 // read error, bailing out
359 //XML_ParserFree(parser);
360 //the parser is freed at another place too
366 // find the document's encoding
367 E( getDocEncoding(S, rawBuffer, theEncoding, this_) );
368 // decide whether to recode or not
369 if (S.recoder().handledByExpat(theEncoding))
374 XML_SetEncoding(parser, "UTF-8");
375 E( S.recoder().openToUTF8(S, theEncoding, cd) );
381 outleft = PARSE_CONV_BUFSIZE;
382 outbuf = (char *) convBuffer;
383 E( S.recoder().conv(S, cd,
384 inbuf, inleft, outbuf, outleft,
396 Err1T(this_, S, E1_BAD_CHAR, theEncoding);
399 assert(!"bad convResult");
401 bytes = PARSE_CONV_BUFSIZE - outleft;
402 res = XML_Parse(parser,convBuffer,bytes,FALSE);
407 res = XML_Parse(parser,rawBuffer,bytes,FALSE);
419 res = XML_Parse(parser, NULL, 0, TRUE);
425 // parsing error to be reported
426 // situation_.setCurrFile(t -> name); is unnecessary as already set
428 // hack to avoid an apparent bug in expat causing crashes when an UTF-8 text
429 // happens to start with a byte order mark by mistake
430 if (!(firstTime && rawBuffer[0] == (char) 0xEF &&
431 rawBuffer[1] == (char) 0xBB && rawBuffer[2] == (char) 0xBF))
432 S.setCurrLine(XML_GetCurrentLineNumber(parser));
433 XML_Error code = XML_GetErrorCode(parser);
434 Str eCodeStr, eNameStr;
435 eCodeStr = (int)code;
436 eNameStr = (char*) XML_ErrorString(code);
437 // XML_ParserFree(parser); -- done later
438 Err2T(this_, S, E_XML, eCodeStr, eNameStr);
441 // remove the 'xml' namespace declarations
443 tcEndNamespace(constructer, "xml");
449 // callback for the document start event
453 void TreeConstructer::tcStartDocument(
456 TreeConstructer *this_ =
457 (TreeConstructer*) constructer;
458 if (this_ -> S.isError())
460 // new slot for count of pending namespaces
461 this_ -> nsCount.append(0);
468 // callback for the element start event
471 void _dump(Tree *tree, QName &name)
473 Str uri = tree -> expand(name.getUri());
474 Str loc = tree -> expand(name.getLocal());
475 Str pre = tree -> expand(name.getPrefix());
477 printf("%s, %s, %s\n", (char*)uri, (char*)pre, (char*)loc);
481 void TreeConstructer::tcStartElement(
482 void *constructer,const char *elName,const char **atts)
484 TreeConstructer *this_ =
485 (TreeConstructer*) constructer;
487 Tree *t = this_ -> theTree;
488 char **p = (char**) atts;
492 BOOL itsExtension = FALSE;
493 Vertex *v; // GP: OK (goes to tree)
494 Attribute *a; // GP: OK (goes to tree)
500 if (this_ -> S.isError())
503 this_ -> S.setCurrLine(elemLine = this_ -> getCurrentLineNumber());
505 //get elName to QName q - DO NOT CHANGE LATER!!
506 if (setQNameFromExpat(this_ -> S, this_, el, elName))
509 itsXSL = (t -> XSLTree) && (t -> expand(el.getUri()) == theXSLTNamespace);
511 //first we have to create all attributes, we need them for extension
512 //and excluded namespace definitions
513 t -> markNamespacePrefixes(this_ -> S); //IMPORTANT
518 if (setQNameFromExpat(this_ -> S, this_, q, (char *)p[0]))
521 //check xml attributes (currently xml:space)
522 if (q.getUri() == t -> stdPhrase(PHRASE_XML_NAMESPACE) &&
523 t -> expand(q.getLocal()) == (const char*)"space")
525 if (!strcmp(p[1], "preserve"))
531 //xsl attributes may occure in literal ements!!
532 //attCode = (itsXSL ?
533 attCode = (itsXSL || (t -> expand(q.getUri()) == theXSLTNamespace) ?
534 (XSL_ATT) lookup(t -> expand(q.getLocal()),xslAttNames) :
540 t -> expandQStr(q, name);
541 this_ -> S.message(MT_ERROR, E_DUPLICIT_ATTRIBUTE,
542 (char*)name, (char*)NULL);
544 a = new(&(t -> getArena())) Attribute(*t, q, p[1],attCode);
545 a -> lineno = this_ -> getCurrentLineNumber();
548 //process extension and excluded prefixes
549 if (attCode == XSLA_EXT_ELEM_PREFIXES ||
550 attCode == XSLA_EXCL_RES_PREFIXES)
552 t -> pushNamespacePrefixes(this_ -> S, a -> cont, attCode);
558 // DETACH: optimize this comparison ###
560 //t -> stdPhrase(PHRASE_XSL_NAMESPACE)))
562 opCode = (XSL_OP) lookup((char*)(t->expand(el.getLocal())),xslOpNames);
563 if (opCode == XSL_NONE)
565 if (this_ -> theDataLine) {
566 if (this_ -> inSAXForAWhile)
567 this_ -> S.setCurrFile(this_ -> theSAXUri);
569 this_ -> S.setCurrFile(this_ -> theDataLine -> fullUri);
571 this_ -> S.message(MT_ERROR, ET_BAD_XSL, (char*)NULL, (char*)NULL);
574 v = new(&(t -> getArena())) XSLElement(*t, el, opCode);
576 else if ((t->XSLTree) && t -> isExtensionUri(el.getUri()))
579 v = new(&(t -> getArena())) ExtensionElement(*t, el);
584 v = new(&(t -> getArena())) Element(*t, el);
585 Processor *proc = this_->S.getProcessor();
586 if ( proc && proc->outputter() )
588 OutputDocument *doc = proc->outputter()->getDocumentForLevel(TRUE);
589 toE(v)->setOutputDocument(doc);
593 //check whether it is top level foreign
596 if ( (t -> stackTop -> vt & VT_TOP_FOREIGN) ||
598 isXSL(t -> stackTop) &&
599 ((toX(t -> stackTop) -> op == XSL_STYLESHEET) ||
600 (toX(t -> stackTop) -> op == XSL_TRANSFORM))) )
602 v -> vt = (VTYPE)(v -> vt | VT_TOP_FOREIGN);
606 v -> lineno = elemLine;
607 t -> appendVertex(this_ -> S, v);
609 //if we are looking at the document element we need to check,
610 // whether the default namespace was declared
611 if (isRoot(v -> parent) && t -> pendingNS().findNdx(UNDEF_PHRASE) == -1)
612 tcStartNamespace(constructer, NULL, ""); //empty default namespace
614 t -> pendingNS().giveCurrent(this_ -> S, toE(v) -> namespaces, t,
615 this_ -> nsCount.last());
616 #ifndef EXPAT_SUPPORTS_TRIPLETS
617 toE(v) -> namespaces.findPrefix(toE(v) -> name);
619 //_dump(t, toE(v) -> name);
621 toE(v) -> namespaces.incPrefixUsage(toE(v) -> name.prefix);
623 //add attributes to the element
624 for (int n = 0; n < auxAtts.number(); n++)
626 const QName *auxName = &(auxAtts[n] -> getName());
627 #ifndef EXPAT_SUPPORTS_TRIPLETS
629 toE(v) -> namespaces.findPrefix(*(const_cast<QName*>(auxName)));
631 t -> appendVertex(this_ -> S, auxAtts[n]);
632 if (auxName -> getPrefix() != UNDEF_PHRASE)
633 toE(v) -> namespaces.incPrefixUsage(auxName -> getPrefix());
640 Bool val = this_ -> preserveSpace.number() ?
641 this_ -> preserveSpace.last() : FALSE;
642 this_ -> preserveSpace.append(val);
645 this_ -> preserveSpace.append(xmlSpace);
646 toE(v) -> preserveSpace = this_ -> preserveSpace.last();
651 //t -> extensionNamespaces(this_ -> S, toE(v));
652 if (toX(v) -> checkAtts(this_ -> S)) return;
653 // also check if a toplevel element does not
654 //have a non-stylesheet parent
655 if (toX(v) -> checkToplevel(this_ -> S)) return;
657 else if (itsExtension)
659 if (toExtension(v) -> checkAtts(this_ -> S)) return;
666 int kLimit = toE(v) -> atts.number();
667 for (k = 0; k < kLimit; k++)
668 if (toA(toE(v) -> atts[k]) -> buildExpr(this_ -> S,
669 TRUE, EX_NONE)) return;
670 // this calls situation.error() on error
673 this_ -> nsCount.append(0);
678 // callback for the element end event
682 void TreeConstructer::tcEndElement(
683 void* constructer, const char* name)
685 TreeConstructer *this_ =
686 (TreeConstructer*) constructer;
687 if (this_ -> S.isError())
689 Tree *t = this_ -> theTree;
690 // destroyed slot for count of pending namespaces
691 this_ -> nsCount.deppend();
693 Vertex *v = NZ( t -> stackTop );
694 t -> flushPendingText();
698 (isXSLElement(v)? toX(v) : cast(Daddy*, v))
703 // situation.error() is called in the following
704 if (toX(v) -> checkChildren(this_ -> S))
707 else if ( isExtension(v) )
709 if (toExtension(v) -> checkChildren(this_ -> S))
714 t -> processVertexAfterParse(this_ -> S, v, this_);
717 t -> popNamespacePrefixes(this_ -> S);
719 //pop preserver space
720 this_ -> preserveSpace.deppend();
726 // callback for the namespace scope start event
730 void TreeConstructer::tcStartNamespace(
731 void* constructer, const char* prefix, const char* uri)
733 tcStartNamespace2(constructer, prefix, uri, false);
736 void TreeConstructer::tcStartNamespace2(
737 void* constructer, const char* prefix, const char* uri, Bool hidden)
739 TreeConstructer *this_ =
740 (TreeConstructer*) constructer;
741 if (this_ -> S.isError())
743 Tree *t = this_ -> theTree;
745 Vertex *newv; // GP: OK (goes to tree)
747 //XML_Parser parser = this_ -> theParser;
749 Phrase prefixPh, uriPh;
752 t -> dict().insert(prefix, prefixPh);
756 prefixPh = UNDEF_PHRASE;
758 t -> dict().insert(uri, uriPh);
760 // t -> pendingNS().appendAndSetOrdinal(
761 t -> pendingNS().append(
762 newv = new(&(t -> getArena()))
763 NmSpace(*t, prefixPh, uriPh, hidden));
765 newv -> lineno = this_ -> getCurrentLineNumber();
766 // count of pending namespaces increased
767 this_ -> nsCount[this_ -> nsCount.number()-1]++;
769 // warn on obsolete namespace
770 if (uri && !strcmp(oldXSLTNamespace, uri)) /* _PH_ */
771 this_ -> Warn1(this_ -> S, W1_OLD_NS_USED, (char*)uri)
774 if (prefix && !strcmp(prefix, "xsl") &&
775 uri && strcmp(theXSLTNamespace, uri)) /* _PH_ */
776 this_ -> Warn1(this_ -> S, W1_XSL_NOT_XSL, (char*) uri);
782 // callback for the namespace scope end event
786 void TreeConstructer::tcEndNamespace(
787 void* constructer, const char* prefix)
789 TreeConstructer *this_ =
790 (TreeConstructer*) constructer;
791 if (this_ -> S.isError())
793 Tree *t = this_ -> theTree;
799 prefixPh = t -> dict().lookup(prefix);
801 prefixPh = UNDEF_PHRASE;
802 assert(toNS(t -> pendingNS().last()) -> prefix == prefixPh);
804 t -> pendingNS().freelast(FALSE);
805 // count of pending namespaces decreased
806 this_ -> nsCount[this_ -> nsCount.number()-1]--;
812 // callback for the comment event
816 void TreeConstructer::tcComment(
817 void* constructer, const char* contents)
819 TreeConstructer *this_ =
820 (TreeConstructer*) constructer;
821 if (this_ -> S.isError())
823 Tree *t = this_ -> theTree;
828 Comment *newNode; // GP: OK
829 newNode = new(&(t -> getArena())) Comment(*t, contents);
830 newNode -> lineno = this_ -> getCurrentLineNumber();
832 Processor *proc = this_ -> S.getProcessor();
833 if ( proc && proc->outputter() )
835 OutputDocument *doc = proc->outputter()->getDocumentForLevel(FALSE);
836 newNode -> setOutputDocument(doc);
839 t -> appendVertex(this_ -> S, newNode);
845 // callback for the processing instruction event
849 void TreeConstructer::tcPI(
850 void* constructer, const char* target, const char* contents)
852 TreeConstructer *this_ =
853 (TreeConstructer*) constructer;
854 if (this_ -> S.isError())
856 Tree *t = this_ -> theTree;
861 ProcInstr *newNode; // GP: OK
863 t -> dict().insert(target, targetPh);
865 newNode = new(&(t -> getArena()))
866 ProcInstr(*t, targetPh, contents);
867 newNode -> lineno = this_ -> getCurrentLineNumber();
869 Processor *proc = this_ -> S.getProcessor();
870 if ( proc && proc->outputter() )
872 OutputDocument *doc = proc->outputter()->getDocumentForLevel(FALSE);
873 newNode -> setOutputDocument(doc);
876 t -> appendVertex(this_ -> S, newNode);
882 // callback for the character data ("text") event
886 void TreeConstructer::tcCharacters(
887 void* constructer, const char* contents, int length)
889 TreeConstructer *this_ =
890 (TreeConstructer*) constructer;
891 if (this_ -> S.isError())
893 Tree *t = this_ -> theTree;
895 Vertex *newVertex; // GP: OK
896 if (!!(newVertex = t -> appendText(this_ -> S, (char *) contents, length)))
897 newVertex -> lineno = this_ -> getCurrentLineNumber();
904 // callback for the document end event
908 void TreeConstructer::tcEndDocument(
911 TreeConstructer *this_ =
912 (TreeConstructer*) constructer;
913 if (this_ -> S.isError())
915 // slot for namespaces counted for childs of this element destroyed
916 this_ -> nsCount.deppend();
922 // callback for the unknown encoding event (expat)
923 // needs to have "enc1250.h" included
927 // the unknown encoding handler is no more used:
930 int TreeConstructer::tcUnknownEncoding(
931 void *encodingHandlerData, const char *name, XML_Encoding *info)
934 if (strEqNoCase((char*) name,"windows-1250"))
936 else if (strEqNoCase((char*) name,"iso-8859-2"))
937 theTable = EncLatin2;
941 for (i = 0; i < 0x80; i++)
944 info -> map[i + 0x80] = theTable[i];
946 info -> map[0x7f] = -1;
948 info -> convert = NULL;
949 info -> release = NULL;
956 // callback for the external entity reference event (expat)
960 int TreeConstructer::tcExternalEntityRef(
961 XML_Parser parser, const char* context, const char* base,
962 const char* systemId, const char* publicId)
964 TreeConstructer *this_ =
965 (TreeConstructer*) XML_GetUserData(parser);
968 if ( publicId && ! this_ -> S.hasFlag(SAB_PARSE_PUBLIC_ENTITIES))
971 if (this_ -> S.isError())
973 Tree *t = this_ -> theTree;
975 this_ -> Log1(this_ -> S, L1_READING_EXT_ENTITY, systemId);
976 XML_Parser newParser =
977 XML_ExternalEntityParserCreate(parser, context, /* encoding= */ NULL);
983 makeAbsoluteURI(this_ -> S,systemId, base, absolute);
984 XML_SetBase(newParser, absolute); //Christian + PH
986 GP(DataLine) newDL = new DataLine;
987 if ( (*newDL).open(this_ -> S, absolute, DLMODE_READ, NULL) )
989 XML_ParserFree(newParser);
994 if (NZ(this_->S.getProcessor())->addLineNoTree(this_ -> S, newDL, absolute,
995 t -> XSLTree) || !newDL)
997 XML_ParserFree(newParser);
1002 TreeConstructer *newTC;
1003 MT( this_, this_ -> S, newTC = new TreeConstructer(this_ -> S));
1005 // record subtree information for the external entity
1006 // XSL_NONE stands for 'external entity'
1007 eFlag code = t -> startSubtree(this_ -> S, absolute, XSL_NONE, TRUE);
1010 code = newTC -> parseDataLineUsingGivenExpat(this_ -> S, t, newDL, newParser);
1011 t -> endSubtree(this_ -> S, XSL_NONE);
1013 (*newDL).close(this_ -> S);
1014 XML_ParserFree(newParser);
1016 return code ? 0 : 1;
1019 void TreeConstructer::tcEntityDecl(void *userData, const char *entityName,
1020 int is_parameter_entity, const char *value,
1021 int value_length, const char *base,
1022 const char *systemId, const char *publicId,
1023 const char *notationName)
1025 TreeConstructer *this_ = (TreeConstructer*) userData;
1028 Str name = entityName;
1030 makeAbsoluteURI(this_ -> S, systemId, base, absolute);
1031 this_ -> theTree -> setUnparsedEntityUri( name, absolute );
1035 /* methods for internal sax handler */
1036 void TreeConstructer::saxStartDocument(void* userData,
1037 SablotHandle processor_)
1039 tcStartDocument(userData);
1042 void TreeConstructer::saxStartElement(void *constructer,
1043 SablotHandle processor_,
1044 const char *elName, const char **atts)
1046 tcStartElement(constructer, elName, atts);
1049 void TreeConstructer::saxEndElement(void* constructer,
1050 SablotHandle processor_,
1053 tcEndElement(constructer, name);
1056 void TreeConstructer::saxStartNamespace(void* userData,
1057 SablotHandle processor_,
1058 const char* prefix, const char* uri)
1060 tcStartNamespace(userData, prefix, uri);
1063 void TreeConstructer::saxStartNamespace2(void* userData,
1064 SablotHandle processor_,
1065 const char* prefix, const char* uri,
1068 tcStartNamespace2(userData, prefix, uri, hidden);
1071 void TreeConstructer::saxEndNamespace(void* constructer,
1072 SablotHandle processor_,
1075 tcEndNamespace(constructer, prefix);
1078 void TreeConstructer::saxComment(void* constructer,
1079 SablotHandle processor_,
1080 const char* contents)
1082 tcComment(constructer, contents);
1085 void TreeConstructer::saxPI(void* constructer,
1086 SablotHandle processor_,
1087 const char* target, const char* contents)
1089 tcPI(constructer, target, contents);
1092 void TreeConstructer::saxCharacters(void* constructer,
1093 SablotHandle processor_,
1094 const char* contents, int length)
1096 tcCharacters(constructer, contents, length);
1099 void TreeConstructer::saxEndDocument(void* constructer,
1100 SablotHandle processor_)
1102 tcEndDocument(constructer);
1105 /* static MUST NOT RELY ON EXPAT_SUPPORTS_TRIPLETS*/
1106 eFlag TreeConstructer::setQNameFromExpat(Sit S, TreeConstructer* this_, QName& qname_, const char* text)
1108 Tree *t = this_ -> theTree;
1109 char *p = (char*) text,
1110 *q = strchr(p, THE_NAMESPACE_SEPARATOR);
1115 qname_.setUri(t -> unexpand(p));
1119 q = strchr(p, THE_NAMESPACE_SEPARATOR);
1122 qname_.setLocal(t -> unexpand(p));
1126 msg += t -> expand(qname_.getUri());
1128 msg += t -> expand(qname_.getLocal());
1129 Err1T(this_, S, E1_EXTRA_COLON, (char *)msg);
1131 //read the prefix - should append only if XML_SetReturnNSTriplet
1136 qname_.setPrefix(t -> unexpand(q + 1));
1141 qname_.uri = UNDEF_PHRASE;
1142 qname_.setLocal(t -> unexpand(p));
1144 qname_.prefix = UNDEF_PHRASE;
1145 if (!!(isColon = strchr(p,':')))
1149 // fixing what appears a bug in expat
1150 //- sometimes the xml:lang attr arrives unexpanded
1151 // apparently only in XSL and when it's not at the top level
1152 if (!strEqNoCase(p,"xml"))
1153 Err1T(this_, S, ET_BAD_PREFIX,p)
1156 qname_.setLocal(t -> unexpand(isColon + 1));
1157 qname_.setUri(t -> stdPhrase(PHRASE_XML_NAMESPACE));
1158 qname_.setPrefix(t -> unexpand((char*)"xml"));
1159 // E( t -> dict().insert(S, "xml",qname_.getPrefix) );
1166 void TreeConstructer::report(Sit S, MsgType type, MsgCode code,
1167 const Str& arg1, const Str& arg2) const
1170 S.setCurrFile(theDataLine -> fullUri);
1171 S.setCurrLine(getCurrentLineNumber());
1172 S.message(type, code, arg1, arg2);