Xalan-C++ API Documentation

The Xalan C++ XSLT Processor Version 1.10

FormatterToXMLUnicode.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #if !defined(FORMATTERTOXML_UNICODE_HEADER_GUARD_1357924680)
17 #define FORMATTERTOXML_UNICODE_HEADER_GUARD_1357924680
18 
19 
20 // Base include file. Must be first.
22 
23 
24 
26 
27 
28 
29 #include "xercesc/sax/AttributeList.hpp"
30 
31 
32 
36 
37 
38 
40 
41 
42 
43 XALAN_CPP_NAMESPACE_BEGIN
44 
45 
49 template<
50  class UnicodeWriter,
51  class ConstantsType,
52  class CharPredicate,
53  class IndentHandler,
56 {
57 public:
58 
59  typedef typename UnicodeWriter::value_type value_type;
60 
61  enum
62  {
63  eDefaultIndentAmount = 0
64  };
65 
83  MemoryManager& theManager,
84  Writer& writer,
85  const XalanDOMString& encoding,
86  const XalanDOMString& doctypeSystem = s_emptyString,
87  const XalanDOMString& doctypePublic = s_emptyString,
88  bool xmlDecl = true,
89  const XalanDOMString& standalone = s_emptyString,
90  size_type indent = eDefaultIndentAmount) :
92  theManager,
93  XMLVersion,
94  encoding,
95  doctypeSystem,
96  doctypePublic,
97  xmlDecl,
98  standalone),
99  m_stringBuffer(theManager),
100  m_writer(writer, theManager),
101  m_constants(),
102  m_charPredicate(),
103  m_indentHandler(m_writer , indent)
104  {
105  }
106 
107  static FormatterToXMLUnicode*
108  create(
109  MemoryManagerType& theManager,
110  Writer& writer,
111  const XalanDOMString& encoding,
112  const XalanDOMString& doctypeSystem = s_emptyString,
113  const XalanDOMString& doctypePublic = s_emptyString,
114  bool xmlDecl = true,
115  const XalanDOMString& standalone = s_emptyString,
116  size_type indent = eDefaultIndentAmount)
117  {
118 
119  typedef FormatterToXMLUnicode ThisType;
120 
121  XalanMemMgrAutoPtr<ThisType, false> theGuard( theManager , (ThisType*)theManager.allocate(sizeof(ThisType)));
122 
123  ThisType* theResult = theGuard.get();
124 
125  new (theResult) ThisType(
126  theManager,
127  writer,
128  encoding,
129  doctypeSystem,
130  doctypePublic,
131  xmlDecl,
132  standalone,
133  indent);
134 
135  theGuard.release();
136 
137  return theResult;
138  }
139 
140  virtual
142  {
143  }
144 
145  Writer*
146  getWriter() const
147  {
148  return m_writer.getWriter();
149  }
150 
151  // These are inherited from XalanXMLSerializerBase...
152 
153  virtual void
155  {
156  m_indentHandler.setStartNewLine(true);
157 
158  m_indentHandler.indent();
159 
160  flushBuffer();
161  }
162 
163  virtual void
165  const XMLCh* const name,
166  AttributeList& attrs)
167  {
168  generateDoctypeDecl(name);
169 
170  writeParentTagEnd();
171 
172  m_indentHandler.setPreserve(false);
173 
174  m_indentHandler.indent();
175 
176  m_indentHandler.setStartNewLine(true);
177 
179 
180  writeName(name);
181 
182  const unsigned int nAttrs = attrs.getLength();
183 
184  for (unsigned int i = 0; i < nAttrs ; i++)
185  {
186  processAttribute(attrs.getName(i), attrs.getValue(i));
187  }
188 
189  // Flag the current element as not yet having any children.
191 
192  m_indentHandler.increaseIndent();
193 
194  m_indentHandler.setPrevText(false);
195  }
196 
197  virtual void
198  endElement(const XMLCh* const name)
199  {
200  m_indentHandler.decreaseIndent();
201 
202  const bool hasChildNodes = childNodesWereAdded();
203 
204  if (hasChildNodes == true)
205  {
206  m_indentHandler.indent();
207 
209  m_writer.write(value_type(XalanUnicode::charSolidus));
210 
211  writeName(name);
212  }
213  else
214  {
215  if(m_spaceBeforeClose == true)
216  {
217  m_writer.write(value_type(XalanUnicode::charSpace));
218  }
219 
220  m_writer.write(value_type(XalanUnicode::charSolidus));
221  }
222 
224 
225  if (hasChildNodes == true)
226  {
227  m_indentHandler.pop_preserve();
228  }
229 
230  m_indentHandler.setPrevText(false);
231  }
232 
233  virtual void
235  const XMLCh* const chars,
236  const unsigned int length)
237  {
238  writeParentTagEnd();
239 
240  m_indentHandler.setPreserve(true);
241 
242  m_writer.write(chars, length);
243  }
244 
245 
246  virtual void
247  entityReference(const XMLCh* const name)
248  {
249  writeParentTagEnd();
250 
251  m_indentHandler.indent();
252 
253  m_writer.write(value_type(XalanUnicode::charAmpersand));
254 
255  writeName(name);
256 
257  m_writer.write(value_type(XalanUnicode::charSemicolon));
258  }
259 
260  virtual void
261  comment(const XMLCh* const data)
262  {
263  writeParentTagEnd();
264 
265  m_indentHandler.indent();
266 
269  m_writer.write(value_type(XalanUnicode::charHyphenMinus));
270  m_writer.write(value_type(XalanUnicode::charHyphenMinus));
271 
272  writeNormalizedData(data, XalanDOMString::length(data));
273 
274  m_writer.write(value_type(XalanUnicode::charHyphenMinus));
275  m_writer.write(value_type(XalanUnicode::charHyphenMinus));
277 
278  m_indentHandler.setStartNewLine(true);
279  }
280 
281  virtual const XalanDOMString&
282  getEncoding() const
283  {
284  return m_constants.s_encodingString;
285  }
286 
287 protected:
288 
289  virtual void
291  {
292  m_writer.flushBuffer();
293  }
294 
295  void
297  {
298  // "<?xml version=\""
299  m_writer.write(
300  m_constants.s_xmlHeaderStartString,
301  m_constants.s_xmlHeaderStartStringLength);
302 
303  if (length(m_version) != 0)
304  {
305  m_writer.write(m_version);
306  }
307  else
308  {
309  m_writer.write(
310  m_constants.s_defaultVersionString,
311  m_constants.s_defaultVersionStringLength);
312  }
313 
314  // "\" encoding=\""
315  m_writer.write(
316  m_constants.s_xmlHeaderEncodingString,
317  m_constants.s_xmlHeaderEncodingStringLength);
318 
319  m_writer.write(m_encoding);
320 
321  if (length(m_standalone) != 0)
322  {
323  m_writer.write(
324  m_constants.s_xmlHeaderStandaloneString,
325  m_constants.s_xmlHeaderStandaloneStringLength);
326 
327  m_writer.write(m_standalone);
328  }
329 
330  m_writer.write(
331  m_constants.s_xmlHeaderEndString,
332  m_constants.s_xmlHeaderEndStringLength);
333 
334  if (getNeedToOutputDoctypeDecl() == false)
335  {
336  m_indentHandler.outputLineSep();
337  }
338  }
339 
340 
341  void
342  writeDoctypeDecl(const XalanDOMChar* name)
343  {
344  // "<!DOCTYPE "
345  m_writer.write(
346  m_constants.s_doctypeHeaderStartString,
347  m_constants.s_doctypeHeaderStartStringLength);
348 
349  m_writer.write(name);
350 
351  if(length(m_doctypePublic) != 0)
352  {
353  // " PUBLIC \""
354  m_writer.write(
355  m_constants.s_doctypeHeaderPublicString,
356  m_constants.s_doctypeHeaderPublicStringLength);
357 
358  writeName(m_doctypePublic.c_str());
359 
360  m_writer.write(value_type(XalanUnicode::charQuoteMark));
361  m_writer.write(value_type(XalanUnicode::charSpace));
362  m_writer.write(value_type(XalanUnicode::charQuoteMark));
363  }
364  else
365  {
366  // " SYSTEM \""
367  m_writer.write(
368  m_constants.s_doctypeHeaderSystemString,
369  m_constants.s_doctypeHeaderSystemStringLength);
370  }
371 
372  writeName(m_doctypeSystem.c_str());
373 
374  m_writer.write(value_type(XalanUnicode::charQuoteMark));
376 
377  outputNewline();
378  }
379 
380 
381  void
383  const XMLCh* target,
384  const XMLCh* data)
385  {
386  writeParentTagEnd();
387 
388  m_indentHandler.indent();
389 
392  writeName(target);
393 
394  const XalanDOMString::size_type len = length(data);
395 
396  // We need to make sure there is a least one whitespace character
397  // between the target and the data.
398  if ( len > 0 && !isXMLWhitespace(data[0]))
399  {
400  m_writer.write(value_type(XalanUnicode::charSpace));
401  }
402 
403  writeNormalizedData(data, len);
404 
407 
408  // If outside of an element, then put in a new line. This whitespace
409  // is not significant.
410  if (outsideDocumentElement() == true)
411  {
412  outputNewline();
413  }
414  }
415 
416  void
418  const XMLCh* chars,
419  unsigned int length)
420  {
421  assert(length != 0);
422 
423  writeParentTagEnd();
424 
425  m_indentHandler.setPreserve(true);
426 
427  unsigned int i = 0;
428  unsigned int firstIndex = 0;
429 
430  while(i < length)
431  {
432  const XalanDOMChar ch = chars[i];
433 
434  if(m_charPredicate.range(ch) == true)
435  {
436  safeWriteContent(chars + firstIndex, i - firstIndex);
437 
438  i = writeNormalizedCharBig(chars, i, length);
439 
440  ++i;
441 
442  firstIndex = i;
443  }
444  else if(m_charPredicate.content(ch) == false)
445  {
446  ++i;
447  }
448  else
449  {
450  safeWriteContent(chars + firstIndex, i - firstIndex);
451 
452  writeDefaultEscape(ch);
453 
454  ++i;
455 
456  firstIndex = i;
457  }
458  }
459 
460  safeWriteContent(chars + firstIndex, i - firstIndex);
461 
462  m_indentHandler.setPrevText(true);
463  }
464 
465 
466  void
468  const XMLCh* chars,
469  unsigned int length)
470  {
471  assert(length != 0);
472 
473  writeParentTagEnd();
474 
475  m_indentHandler.setPreserve(true);
476 
477  m_indentHandler.indent();
478 
479  m_writer.write(
480  m_constants.s_cdataOpenString,
481  m_constants.s_cdataOpenStringLength);
482 
483  bool outsideCDATA = false;
484 
485  writeCDATAChars(chars, length, outsideCDATA);
486 
487  if (outsideCDATA == false)
488  {
489  m_writer.write(
490  m_constants.s_cdataCloseString,
491  m_constants.s_cdataCloseStringLength);
492  }
493  }
494 
498  void
500  {
501  m_writer.outputNewline();
502  }
503 
507  void
508  writeDefaultEscape(XalanDOMChar ch)
509  {
510  assert(m_charPredicate.content(ch) == true);
511 
512  if(!writeDefaultEntity(ch))
513  {
514  if (XalanUnicode::charLF == ch)
515  {
516  outputNewline();
517  }
518  else
519  {
520  if(m_charPredicate.isForbidden(ch) == true)
521  {
523  ch,
524  m_version,
525  getMemoryManager());
526  }
527  else
528  {
529  writeNumericCharacterReference(ch);
530  }
531  }
532  }
533  }
534 
538  void
539  writeDefaultAttributeEscape(XalanDOMChar ch)
540  {
541  assert(m_charPredicate.attribute(ch) == true);
542 
543  if(writeDefaultAttributeEntity(ch) == false)
544  {
545  if(m_charPredicate.isForbidden(ch) == true)
546  {
548  ch,
549  m_version,
550  getMemoryManager());
551  }
552  else
553  {
554  writeNumericCharacterReference(ch);
555  }
556 
557  }
558  }
559 
564  bool
565  writeDefaultEntity(XalanDOMChar ch)
566  {
568  {
569  m_writer.write(
570  m_constants.s_lessThanEntityString,
571  m_constants.s_lessThanEntityStringLength);
572  }
573  else if (XalanUnicode::charGreaterThanSign == ch)
574  {
575  m_writer.write(
576  m_constants.s_greaterThanEntityString,
577  m_constants.s_greaterThanEntityStringLength);
578  }
579  else if (XalanUnicode::charAmpersand == ch)
580  {
581  m_writer.write(
582  m_constants.s_ampersandEntityString,
583  m_constants.s_ampersandEntityStringLength);
584  }
585  else
586  {
587  return false;
588  }
589 
590  return true;
591  }
592 
597  bool
598  writeDefaultAttributeEntity(XalanDOMChar ch)
599  {
600  if (writeDefaultEntity(ch) == true)
601  {
602  return true;
603  }
604  else if (XalanUnicode::charQuoteMark == ch)
605  {
606  m_writer.write(
607  m_constants.s_quoteEntityString,
608  m_constants.s_quoteEntityStringLength);
609  }
610  else
611  {
612  return false;
613  }
614 
615  return true;
616  }
617 
622  void
623  writeParentTagEnd()
624  {
625  if(markParentForChildren() == true)
626  {
628 
629  m_indentHandler.setPrevText(false);
630 
631  m_indentHandler.push_preserve();
632  }
633  }
634 
642  writeNormalizedChar(
643  XalanDOMChar ch,
644  const XalanDOMChar chars[],
647  {
648  if (XalanUnicode::charLF == ch)
649  {
650  outputNewline();
651  }
652  else
653  {
654  if(m_charPredicate.isCharRefForbidden(ch))
655  {
657  ch,
658  m_version,
659  getMemoryManager());
660  }
661  else
662  {
663  start = m_writer.write( chars, start, length);
664  }
665  }
666 
667  return start;
668  }
669 
670  void
671  writeNumericCharacterReference(unsigned long theNumber)
672  {
673  m_writer.write(value_type(XalanUnicode::charAmpersand));
674  m_writer.write(value_type(XalanUnicode::charNumberSign));
675 
676  m_writer.write(UnsignedLongToDOMString(theNumber, m_stringBuffer));
677  clear(m_stringBuffer);
678 
679  m_writer.write(value_type(XalanUnicode::charSemicolon));
680  }
681 
683  writeNormalizedCharBig(
684  const XalanDOMChar chars[],
687  {
688  assert( start < length);
689 
690  const XalanDOMChar ch = chars[start];
691 
692  assert(m_charPredicate.range(ch) == true);
693 
694  if (XMLVersion == XML_VERSION_1_1 &&
696  {
697  writeNumericCharacterReference(ch);
698  }
699  else
700  {
701  start = m_writer.write(chars, start, length);
702  }
703 
704  return start;
705  }
706 
713  void
714  writeCDATAChars(
715  const XalanDOMChar chars[],
717  bool& outsideCDATA)
718  {
720 
721  while(i < length)
722  {
723  // If "]]>", which would close the CDATA appears in
724  // the content, we have to put the first two characters
725  // in the CDATA section, close the CDATA section, then
726  // open a new one and add the last character.
727 
728  const XalanDOMChar theChar = chars[i];
729 
730  if (theChar == XalanUnicode::charRightSquareBracket &&
731  i - length > 2 &&
732  XalanUnicode::charRightSquareBracket == chars[i + 1] &&
733  XalanUnicode::charGreaterThanSign == chars[i + 2])
734  {
735  if (outsideCDATA == true)
736  {
737  m_writer.write(
738  m_constants.s_cdataCloseString,
739  m_constants.s_cdataCloseStringLength);
740  }
741 
744 
745  m_writer.write(
746  m_constants.s_cdataCloseString,
747  m_constants.s_cdataCloseStringLength);
748 
749  m_writer.write(
750  m_constants.s_cdataOpenString,
751  m_constants.s_cdataOpenStringLength);
752 
754 
755  outsideCDATA = false;
756 
757  i += 2;
758  }
759  else
760  {
761  if (XalanUnicode::charLF == theChar)
762  {
763  outputNewline();
764  }
765  else if(m_charPredicate.isCharRefForbidden(theChar))
766  {
768  theChar,
769  m_version,
770  getMemoryManager());
771  }
772  else
773  {
774  i = m_writer.writeCDATAChar(chars, i, length, outsideCDATA);
775  }
776  }
777 
778  ++i;
779  }
780 
781  if(outsideCDATA == true)
782  {
783  m_writer.write(
784  m_constants.s_cdataOpenString,
785  m_constants.s_cdataOpenStringLength);
786  }
787  }
788 
789 
796  void
797  writeAttrString(
798  const XalanDOMChar* theString,
799  XalanDOMString::size_type theStringLength)
800  {
801  assert(theString != 0);
802 
804  XalanDOMString::size_type firstIndex = 0;
805 
806  while(i < theStringLength)
807  {
808  const XalanDOMChar ch = theString[i];
809 
810  if(m_charPredicate.range(ch) == true)
811  {
812  safeWriteContent(theString + firstIndex, i - firstIndex);
813 
814  i = writeNormalizedCharBig(theString, i, theStringLength);
815 
816  ++i;
817 
818  firstIndex = i;
819  }
820  else if (m_charPredicate.attribute(ch) == false)
821  {
822  ++i;
823  }
824  else
825  {
826  safeWriteContent(theString + firstIndex, i - firstIndex);
827 
828  writeDefaultAttributeEscape(ch);
829 
830  ++i;
831 
832  firstIndex = i;
833  }
834  }
835 
836  safeWriteContent(theString + firstIndex, i - firstIndex);
837  }
838 
839 private:
840 
846  void
847  processAttribute(
848  const XalanDOMChar* name,
849  const XalanDOMChar* value)
850  {
851  m_writer.write(value_type(XalanUnicode::charSpace));
852  writeName(name);
853  m_writer.write(value_type(XalanUnicode::charEqualsSign));
854  m_writer.write(value_type(XalanUnicode::charQuoteMark));
855  writeAttrString(value, length(value));
856  m_writer.write(value_type(XalanUnicode::charQuoteMark));
857  }
858 
864  void
865  writeNormalizedData(
866  const XalanDOMChar* theData,
867  XalanDOMString::size_type theLength)
868  {
869  for (XalanDOMString::size_type i = 0; i < theLength; ++i)
870  {
871  const XalanDOMChar theChar = theData[i];
872 
873  i = writeNormalizedChar(theChar, theData, i, theLength);
874  }
875  }
876 
877  void
878  safeWriteContent(
879  const XalanDOMChar* theChars,
880  XalanDOMString::size_type theLength)
881  {
882  for(size_type i = 0; i < theLength; ++i)
883  {
884  m_writer.write(value_type(theChars[i]));
885  }
886  }
887 
888  void
889  writeName(const XalanDOMChar* theChars)
890  {
891  assert( theChars != 0);
892 
893  m_writer.writeNameChar(theChars, length(theChars));
894  }
895 
896 private:
897 
898  // These are not implemented.
900 
902  operator=(const FormatterToXMLUnicode&);
903 
904  bool
905  operator==(const FormatterToXMLUnicode&) const;
906 
907 
908  // Data members...
909  XalanDOMString m_stringBuffer;
910 
911  UnicodeWriter m_writer;
912 
913  ConstantsType m_constants;
914 
915  CharPredicate m_charPredicate;
916 
917  IndentHandler m_indentHandler;
918 };
919 
920 
921 
922 XALAN_CPP_NAMESPACE_END
923 
924 
925 
926 #endif // FORMATTERTOXML_UNICODE_HEADER_GUARD_1357924680

Interpreting class diagrams

Doxygen and GraphViz are used to generate this API documentation from the Xalan-C header files.

dot

Xalan-C++ XSLT Processor Version 1.10
Copyright © 1999-2004 The Apache Software Foundation. All Rights Reserved.

Apache Logo