IDOMPrint.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:26k
源码类别:

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 2001 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 2001, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Id: IDOMPrint.cpp,v 1.6 2001/10/19 18:27:34 tng Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  This sample program which invokes the DOMParser to build a DOM tree for
  61. //  the specified input file. It then walks the tree, and prints out the data
  62. //  as an XML file.
  63. //
  64. //   Limitations:
  65. //      1.  The encoding="xxx" clause in the XML header should reflect
  66. //          the system local code page, but does not.
  67. //      2.  Cases where the XML data contains characters that can not
  68. //          be represented in the system local code page are not handled.
  69. //      3.  Enabled namespace processing won't affect the output, since
  70. //          DOM doesn't do namespace yet. But it will confirm that all
  71. //          prefixes are correctly mapped, else you'll get errors.
  72. // ---------------------------------------------------------------------------
  73. // ---------------------------------------------------------------------------
  74. //  Includes
  75. // ---------------------------------------------------------------------------
  76. #include <util/PlatformUtils.hpp>
  77. #include <util/XMLString.hpp>
  78. #include <util/XMLUniDefs.hpp>
  79. #include <framework/XMLFormatter.hpp>
  80. #include <util/TranscodingException.hpp>
  81. #include <idom/IDOM_DOMException.hpp>
  82. #include <parsers/IDOMParser.hpp>
  83. #include <idom/IDOM.hpp>
  84. #include "IDOMTreeErrorReporter.hpp"
  85. #include <string.h>
  86. #include <stdlib.h>
  87. // ---------------------------------------------------------------------------
  88. //  Local const data
  89. //
  90. //  Note: This is the 'safe' way to do these strings. If you compiler supports
  91. //        L"" style strings, and portability is not a concern, you can use
  92. //        those types constants directly.
  93. // ---------------------------------------------------------------------------
  94. static const XMLCh  gEndElement[] = { chOpenAngle, chForwardSlash, chNull };
  95. static const XMLCh  gEndPI[] = { chQuestion, chCloseAngle, chNull};
  96. static const XMLCh  gStartPI[] = { chOpenAngle, chQuestion, chNull };
  97. static const XMLCh  gXMLDecl1[] =
  98. {
  99.         chOpenAngle, chQuestion, chLatin_x, chLatin_m, chLatin_l
  100.     ,   chSpace, chLatin_v, chLatin_e, chLatin_r, chLatin_s, chLatin_i
  101.     ,   chLatin_o, chLatin_n, chEqual, chDoubleQuote, chDigit_1
  102.     ,   chPeriod, chDigit_0, chNull
  103. };
  104. static const XMLCh  gXMLDecl2[] =
  105. {
  106.         chDoubleQuote, chSpace, chLatin_e, chLatin_n, chLatin_c
  107.     ,   chLatin_o, chLatin_d, chLatin_i, chLatin_n, chLatin_g, chEqual
  108.     ,   chDoubleQuote, chNull
  109. };
  110. static const XMLCh  gXMLDecl3[] =
  111. {
  112.         chDoubleQuote, chQuestion, chCloseAngle
  113.     ,   chLF, chNull
  114. };
  115. static const XMLCh  gStartCDATA[] =
  116. {
  117.         chOpenAngle, chBang, chOpenSquare, chLatin_C, chLatin_D,
  118.         chLatin_A, chLatin_T, chLatin_A, chOpenSquare, chNull
  119. };
  120. static const XMLCh  gEndCDATA[] =
  121. {
  122.     chCloseSquare, chCloseSquare, chCloseAngle, chNull
  123. };
  124. static const XMLCh  gStartComment[] =
  125. {
  126.     chOpenAngle, chBang, chDash, chDash, chNull
  127. };
  128. static const XMLCh  gEndComment[] =
  129. {
  130.     chDash, chDash, chCloseAngle, chNull
  131. };
  132. static const XMLCh  gStartDoctype[] =
  133. {
  134.     chOpenAngle, chBang, chLatin_D, chLatin_O, chLatin_C, chLatin_T,
  135.     chLatin_Y, chLatin_P, chLatin_E, chSpace, chNull
  136. };
  137. static const XMLCh  gPublic[] =
  138. {
  139.     chLatin_P, chLatin_U, chLatin_B, chLatin_L, chLatin_I,
  140.     chLatin_C, chSpace, chDoubleQuote, chNull
  141. };
  142. static const XMLCh  gSystem[] =
  143. {
  144.     chLatin_S, chLatin_Y, chLatin_S, chLatin_T, chLatin_E,
  145.     chLatin_M, chSpace, chDoubleQuote, chNull
  146. };
  147. static const XMLCh  gStartEntity[] =
  148. {
  149.     chOpenAngle, chBang, chLatin_E, chLatin_N, chLatin_T, chLatin_I,
  150.     chLatin_T, chLatin_Y, chSpace, chNull
  151. };
  152. static const XMLCh  gNotation[] =
  153. {
  154.     chLatin_N, chLatin_D, chLatin_A, chLatin_T, chLatin_A,
  155.     chSpace, chDoubleQuote, chNull
  156. };
  157. // ---------------------------------------------------------------------------
  158. //  Local classes
  159. // ---------------------------------------------------------------------------
  160. class IDOMPrintFormatTarget : public XMLFormatTarget
  161. {
  162. public:
  163.     IDOMPrintFormatTarget()  {};
  164.     ~IDOMPrintFormatTarget() {};
  165.     // -----------------------------------------------------------------------
  166.     //  Implementations of the format target interface
  167.     // -----------------------------------------------------------------------
  168.     void writeChars(const   XMLByte* const  toWrite,
  169.                     const   unsigned int    count,
  170.                             XMLFormatter * const formatter)
  171.     {
  172.         // Surprisingly, Solaris was the only platform on which
  173.         // required the char* cast to print out the string correctly.
  174.         // Without the cast, it was printing the pointer value in hex.
  175.         // Quite annoying, considering every other platform printed
  176.         // the string with the explicit cast to char* below.
  177.         cout.write((char *) toWrite, (int) count);
  178.     };
  179. private:
  180.     // -----------------------------------------------------------------------
  181.     //  Unimplemented methods.
  182.     // -----------------------------------------------------------------------
  183.     IDOMPrintFormatTarget(const IDOMPrintFormatTarget& other);
  184.     void operator=(const IDOMPrintFormatTarget& rhs);
  185. };
  186. // ---------------------------------------------------------------------------
  187. //  Local data
  188. //
  189. //  gXmlFile
  190. //      The path to the file to parser. Set via command line.
  191. //
  192. //  gDoNamespaces
  193. //      Indicates whether namespace processing should be done.
  194. //
  195. //  gDoSchema
  196. //      Indicates whether schema processing should be done.
  197. //
  198. //  gSchemaFullChecking
  199. //      Indicates whether full schema constraint checking should be done.
  200. //
  201. //  gDoCreate
  202. //      Indicates whether entity reference nodes needs to be created or not
  203. //      Defaults to false
  204. //
  205. //  gEncodingName
  206. //      The encoding we are to output in. If not set on the command line,
  207. //      then it is defaults to the encoding of the input XML file.
  208. //
  209. //  gValScheme
  210. //      Indicates what validation scheme to use. It defaults to 'auto', but
  211. //      can be set via the -v= command.
  212. //
  213. // ---------------------------------------------------------------------------
  214. static char*                    gXmlFile               = 0;
  215. static bool                     gDoNamespaces          = false;
  216. static bool                     gDoSchema              = false;
  217. static bool                     gSchemaFullChecking    = false;
  218. static bool                     gDoCreate              = false;
  219. static const XMLCh*             gEncodingName          = 0;
  220. static bool                     gEncodingNameisOnHeap  = false;
  221. static XMLFormatter::UnRepFlags gUnRepFlags            = XMLFormatter::UnRep_CharRef;
  222. static IDOMParser::ValSchemes    gValScheme             = IDOMParser::Val_Auto;
  223. static XMLFormatter*            gFormatter             = 0;
  224. // ---------------------------------------------------------------------------
  225. //  Forward references
  226. // ---------------------------------------------------------------------------
  227. void     usage();
  228. ostream& operator<<(ostream& target, const XMLCh * toWrite);
  229. ostream& operator<<(ostream& target, IDOM_Node *toWrite);
  230. // XMLFormatter& operator<< (XMLFormatter& strm, const XMLCh *s);
  231. // ---------------------------------------------------------------------------
  232. //
  233. //  Usage()
  234. //
  235. // ---------------------------------------------------------------------------
  236. void usage()
  237. {
  238.     cout << "nUsage:n"
  239.             "    IDOMPrint [options] <XML file>nn"
  240.             "This program invokes the IDOM parser, and builds the DOM tree.n"
  241.             "It then traverses the DOM tree and prints the contents of then"
  242.             "tree for the specified XML file.nn"
  243.             "Options:n"
  244.             "    -e          create entity reference nodes. Default is no expansion.n"
  245.             "    -u=xxx      Handle unrepresentable chars [fail | rep | ref*].n"
  246.             "    -v=xxx      Validation scheme [always | never | auto*].n"
  247.             "    -n          Enable namespace processing. Default is off.n"
  248.             "    -s          Enable schema processing. Default is off.n"
  249.             "    -f          Enable full schema constraint checking. Defaults is off.n"
  250.             "    -x=XXX      Use a particular encoding for output. Default isn"
  251.             "                the same encoding as the input XML file. UTF-8 ifn"
  252.             "                input XML file has not XML declaration.n"
  253.             "    -?          Show this help.nn"
  254.             "  * = Default if not provided explicitly.nn"
  255.             "The parser has intrinsic support for the following encodings:n"
  256.             "    UTF-8, USASCII, ISO8859-1, UTF-16[BL]E, UCS-4[BL]E,n"
  257.             "    WINDOWS-1252, IBM1140, IBM037.n"
  258.           <<  endl;
  259. }
  260. // ---------------------------------------------------------------------------
  261. //
  262. //  main
  263. //
  264. // ---------------------------------------------------------------------------
  265. int main(int argC, char* argV[])
  266. {
  267.     int retval = 0;
  268.     // Initialize the XML4C2 system
  269.     try
  270.     {
  271.         XMLPlatformUtils::Initialize();
  272.     }
  273.     catch(const XMLException &toCatch)
  274.     {
  275.         cerr << "Error during Xerces-c Initialization.n"
  276.              << "  Exception message:"
  277.              << StrX(toCatch.getMessage()) << endl;
  278.         return 1;
  279.     }
  280.     // Check command line and extract arguments.
  281.     if (argC < 2)
  282.     {
  283.         usage();
  284.         XMLPlatformUtils::Terminate();
  285.         return 1;
  286.     }
  287.     // See if non validating dom parser configuration is requested.
  288.     int parmInd;
  289.     for (parmInd = 1; parmInd < argC; parmInd++)
  290.     {
  291.         // Break out on first parm not starting with a dash
  292.         if (argV[parmInd][0] != '-')
  293.             break;
  294.         // Watch for special case help request
  295.         if (!strcmp(argV[parmInd], "-?"))
  296.         {
  297.             usage();
  298.             XMLPlatformUtils::Terminate();
  299.             return 2;
  300.         }
  301.          else if (!strncmp(argV[parmInd], "-v=", 3)
  302.               ||  !strncmp(argV[parmInd], "-V=", 3))
  303.         {
  304.             const char* const parm = &argV[parmInd][3];
  305.             if (!strcmp(parm, "never"))
  306.                 gValScheme = IDOMParser::Val_Never;
  307.             else if (!strcmp(parm, "auto"))
  308.                 gValScheme = IDOMParser::Val_Auto;
  309.             else if (!strcmp(parm, "always"))
  310.                 gValScheme = IDOMParser::Val_Always;
  311.             else
  312.             {
  313.                 cerr << "Unknown -v= value: " << parm << endl;
  314.                 XMLPlatformUtils::Terminate();
  315.                 return 2;
  316.             }
  317.         }
  318.          else if (!strcmp(argV[parmInd], "-n")
  319.               ||  !strcmp(argV[parmInd], "-N"))
  320.         {
  321.             gDoNamespaces = true;
  322.         }
  323.          else if (!strcmp(argV[parmInd], "-s")
  324.               ||  !strcmp(argV[parmInd], "-S"))
  325.         {
  326.             gDoSchema = true;
  327.         }
  328.          else if (!strcmp(argV[parmInd], "-f")
  329.               ||  !strcmp(argV[parmInd], "-F"))
  330.         {
  331.             gSchemaFullChecking = true;
  332.         }
  333.          else if (!strcmp(argV[parmInd], "-e")
  334.               ||  !strcmp(argV[parmInd], "-E"))
  335.         {
  336.             gDoCreate = true;
  337.         }
  338.          else if (!strncmp(argV[parmInd], "-x=", 3)
  339.               ||  !strncmp(argV[parmInd], "-X=", 3))
  340.         {
  341.              // Get out the encoding name
  342.              gEncodingName = XMLString::transcode( &(argV[parmInd][3]) );
  343.              gEncodingNameisOnHeap = true;
  344.         }
  345.          else if (!strncmp(argV[parmInd], "-u=", 3)
  346.               ||  !strncmp(argV[parmInd], "-U=", 3))
  347.         {
  348.             const char* const parm = &argV[parmInd][3];
  349.             if (!strcmp(parm, "fail"))
  350.                 gUnRepFlags = XMLFormatter::UnRep_Fail;
  351.             else if (!strcmp(parm, "rep"))
  352.                 gUnRepFlags = XMLFormatter::UnRep_Replace;
  353.             else if (!strcmp(parm, "ref"))
  354.                 gUnRepFlags = XMLFormatter::UnRep_CharRef;
  355.             else
  356.             {
  357.                 cerr << "Unknown -u= value: " << parm << endl;
  358.                 XMLPlatformUtils::Terminate();
  359.                 return 2;
  360.             }
  361.         }
  362.         //  else if (!strcmp(argV[parmInd], "-NoEscape"))
  363.         // {
  364.         //     gDoEscapes = false;
  365.         // }
  366.          else
  367.         {
  368.             cerr << "Unknown option '" << argV[parmInd]
  369.                  << "', ignoring it.n" << endl;
  370.         }
  371.     }
  372.     //
  373.     //  And now we have to have only one parameter left and it must be
  374.     //  the file name.
  375.     //
  376.     if (parmInd + 1 != argC)
  377.     {
  378.         usage();
  379.         XMLPlatformUtils::Terminate();
  380.         return 1;
  381.     }
  382.     gXmlFile = argV[parmInd];
  383.     //
  384.     //  Create our parser, then attach an error handler to the parser.
  385.     //  The parser will call back to methods of the ErrorHandler if it
  386.     //  discovers errors during the course of parsing the XML document.
  387.     //
  388.     IDOMParser *parser = new IDOMParser;
  389.     parser->setValidationScheme(gValScheme);
  390.     parser->setDoNamespaces(gDoNamespaces);
  391.     parser->setDoSchema(gDoSchema);
  392.     parser->setValidationSchemaFullChecking(gSchemaFullChecking);
  393.     IDOMTreeErrorReporter *errReporter = new IDOMTreeErrorReporter();
  394.     parser->setErrorHandler(errReporter);
  395.     parser->setCreateEntityReferenceNodes(gDoCreate);
  396.     //
  397.     //  Parse the XML file, catching any XML exceptions that might propogate
  398.     //  out of it.
  399.     //
  400.     bool errorsOccured = false;
  401.     try
  402.     {
  403.         parser->parse(gXmlFile);
  404.     }
  405.     catch (const XMLException& e)
  406.     {
  407.         cerr << "An error occured during parsingn   Message: "
  408.              << StrX(e.getMessage()) << endl;
  409.         errorsOccured = true;
  410.     }
  411.     catch (const IDOM_DOMException& e)
  412.     {
  413.        cerr << "A DOM error occured during parsingn   DOMException code: "
  414.              << e.code << endl;
  415.         errorsOccured = true;
  416.     }
  417.     catch (...)
  418.     {
  419.         cerr << "An error occured during parsingn " << endl;
  420.         errorsOccured = true;
  421.     }
  422.     // If the parse was successful, output the document data from the DOM tree
  423.     if (!errorsOccured && !errReporter->getSawErrors())
  424.     {
  425.         IDOM_Node *doc = parser->getDocument();
  426.         IDOMPrintFormatTarget* formatTarget = new IDOMPrintFormatTarget();
  427.         // Figure out the encoding that we want to use to write the document.
  428.         //   If command line specified, use that,
  429.         //   otherwise use utf-8.
  430.         //
  431.         if (gEncodingName == 0)   // if no encoding specified on command line
  432.         {
  433.             static  const XMLCh utf_8[] = {chLatin_U, chLatin_T, chLatin_F, chDash, chDigit_8, 0};
  434.             gEncodingName = utf_8;
  435.         }
  436.         //
  437.         //  Create the output formatter and actually write the document HERE!
  438.         //
  439.         try
  440.         {
  441.             gFormatter = new XMLFormatter(gEncodingName, formatTarget,
  442.                                           XMLFormatter::NoEscapes, gUnRepFlags);
  443.             //print out the XML Decl node first
  444.             *gFormatter << gXMLDecl1 ;
  445.             *gFormatter << gXMLDecl2 << gEncodingName;
  446.             *gFormatter << gXMLDecl3;
  447.             cout << doc;
  448.             *gFormatter << chLF; // add linefeed in requested output encoding
  449.             cout << flush;
  450.         }
  451.         catch (XMLException& e)
  452.         {
  453.             cerr << "An error occurred during creation of output transcoder. Msg is:"
  454.                 << endl
  455.                 << StrX(e.getMessage()) << endl;
  456.             retval = 4;
  457.         }
  458.         delete formatTarget;
  459.         delete gFormatter;
  460.     }
  461.     else
  462.         retval = 4;
  463.     //
  464.     //  Clean up the error handler. The parser does not adopt handlers
  465.     //  since they could be many objects or one object installed for multiple
  466.     //  handlers.
  467.     //
  468.     delete errReporter;
  469.     //
  470.     //  Delete the parser itself.  Must be done prior to calling Terminate, below.
  471.     //
  472.     delete parser;
  473.     // And call the termination method
  474.     XMLPlatformUtils::Terminate();
  475.     if (gEncodingNameisOnHeap)
  476.         delete (void *)gEncodingName;   // const problems.
  477.     return retval;
  478. }
  479. // ---------------------------------------------------------------------------
  480. //  ostream << DOM_Node
  481. //
  482. //  Stream out a DOM node, and, recursively, all of its children. This
  483. //  function is the heart of writing a DOM tree out as XML source. Give it
  484. //  a document node and it will do the whole thing.
  485. // ---------------------------------------------------------------------------
  486. ostream& operator<<(ostream& target, IDOM_Node *toWrite)
  487. {
  488.     // Get the name and value out for convenience
  489.     const XMLCh *   nodeName = toWrite->getNodeName();
  490.     const XMLCh *   nodeValue = toWrite->getNodeValue();
  491.     unsigned long lent = XMLString::stringLen(nodeValue);
  492.     switch (toWrite->getNodeType())
  493.     {
  494.         case IDOM_Node::TEXT_NODE:
  495.         {
  496.             gFormatter->formatBuf(nodeValue,
  497.                                   lent, XMLFormatter::CharEscapes);
  498.             break;
  499.         }
  500.         case IDOM_Node::PROCESSING_INSTRUCTION_NODE :
  501.         {
  502.             *gFormatter << XMLFormatter::NoEscapes << gStartPI  << nodeName;
  503.             if (lent > 0)
  504.             {
  505.                 *gFormatter << chSpace << nodeValue;
  506.             }
  507.             *gFormatter << XMLFormatter::NoEscapes << gEndPI;
  508.             break;
  509.         }
  510.         case IDOM_Node::DOCUMENT_NODE :
  511.         {
  512.             IDOM_Node *child = toWrite->getFirstChild();
  513.             while( child != 0)
  514.             {
  515.                 target << child;
  516.                 // add linefeed in requested output encoding
  517.                 *gFormatter << chLF;
  518.                 target << flush;
  519.                 child = child->getNextSibling();
  520.             }
  521.             break;
  522.         }
  523.         case IDOM_Node::ELEMENT_NODE :
  524.         {
  525.             // The name has to be representable without any escapes
  526.             *gFormatter  << XMLFormatter::NoEscapes
  527.                          << chOpenAngle << nodeName;
  528.             // Output the element start tag.
  529.             // Output any attributes on this element
  530.             IDOM_NamedNodeMap *attributes = toWrite->getAttributes();
  531.             int attrCount = attributes->getLength();
  532.             for (int i = 0; i < attrCount; i++)
  533.             {
  534.                 IDOM_Node  *attribute = attributes->item(i);
  535.                 //
  536.                 //  Again the name has to be completely representable. But the
  537.                 //  attribute can have refs and requires the attribute style
  538.                 //  escaping.
  539.                 //
  540.                 *gFormatter  << XMLFormatter::NoEscapes
  541.                              << chSpace << attribute->getNodeName()
  542.                              << chEqual << chDoubleQuote
  543.                              << XMLFormatter::AttrEscapes
  544.                              << attribute->getNodeValue()
  545.                              << XMLFormatter::NoEscapes
  546.                              << chDoubleQuote;
  547.             }
  548.             //
  549.             //  Test for the presence of children, which includes both
  550.             //  text content and nested elements.
  551.             //
  552.             IDOM_Node *child = toWrite->getFirstChild();
  553.             if (child != 0)
  554.             {
  555.                 // There are children. Close start-tag, and output children.
  556.                 // No escapes are legal here
  557.                 *gFormatter << XMLFormatter::NoEscapes << chCloseAngle;
  558.                 while( child != 0)
  559.                 {
  560.                     target << child;
  561.                     child = child->getNextSibling();
  562.                 }
  563.                 //
  564.                 // Done with children.  Output the end tag.
  565.                 //
  566.                 *gFormatter << XMLFormatter::NoEscapes << gEndElement
  567.                             << nodeName << chCloseAngle;
  568.             }
  569.             else
  570.             {
  571.                 //
  572.                 //  There were no children. Output the short form close of
  573.                 //  the element start tag, making it an empty-element tag.
  574.                 //
  575.                 *gFormatter << XMLFormatter::NoEscapes << chForwardSlash << chCloseAngle;
  576.             }
  577.             break;
  578.         }
  579.         case IDOM_Node::ENTITY_REFERENCE_NODE:
  580.             {
  581. #if 0
  582.                 IDOM_Node *child;
  583.                 for (child = toWrite->getFirstChild();
  584.                 child != 0;
  585.                 child = child->getNextSibling())
  586.                 {
  587.                     target << child;
  588.                 }
  589. #else
  590.                 //
  591.                 // Instead of printing the refernece tree
  592.                 // we'd output the actual text as it appeared in the xml file.
  593.                 // This would be the case when -e option was chosen
  594.                 //
  595.                     *gFormatter << XMLFormatter::NoEscapes << chAmpersand
  596.                         << nodeName << chSemiColon;
  597. #endif
  598.                 break;
  599.             }
  600.         case IDOM_Node::CDATA_SECTION_NODE:
  601.             {
  602.             *gFormatter << XMLFormatter::NoEscapes << gStartCDATA
  603.                         << nodeValue << gEndCDATA;
  604.             break;
  605.         }
  606.         case IDOM_Node::COMMENT_NODE:
  607.         {
  608.             *gFormatter << XMLFormatter::NoEscapes << gStartComment
  609.                         << nodeValue << gEndComment;
  610.             break;
  611.         }
  612.         case IDOM_Node::DOCUMENT_TYPE_NODE:
  613.             {
  614.             IDOM_DocumentType *doctype = (IDOM_DocumentType *)toWrite;;
  615.             *gFormatter << XMLFormatter::NoEscapes  << gStartDoctype
  616.                         << nodeName;
  617.             const XMLCh  *id = doctype->getPublicId();
  618.             if (id != 0 && *id != 0)
  619.             {
  620.                 *gFormatter << XMLFormatter::NoEscapes << chSpace << gPublic
  621.                     << id << chDoubleQuote;
  622.             }
  623.             id = doctype->getSystemId();
  624.             if (id != 0 && *id != 0)
  625.             {
  626.                 *gFormatter << XMLFormatter::NoEscapes << chSpace
  627.                     << chDoubleQuote << id << chDoubleQuote;
  628.             }
  629.             id = doctype->getSystemId();
  630.             if (id != 0 && *id != 0)
  631.             {
  632.                 *gFormatter << XMLFormatter::NoEscapes << chSpace << gSystem
  633.                     << id << chDoubleQuote;
  634.             }
  635.             id = doctype->getInternalSubset();
  636.             if (id != 0 && *id != 0)
  637.                 *gFormatter << XMLFormatter::NoEscapes << chOpenSquare
  638.                 << id << chCloseSquare;
  639.             *gFormatter << XMLFormatter::NoEscapes << chCloseAngle;
  640.             break;
  641.         }
  642.         case IDOM_Node::ENTITY_NODE:
  643.         {
  644.             *gFormatter << XMLFormatter::NoEscapes << gStartEntity
  645.                         << nodeName;
  646.             const XMLCh * id = ((IDOM_Entity *)toWrite)->getPublicId();
  647.             if (id != 0)
  648.                 *gFormatter << XMLFormatter::NoEscapes << gPublic
  649.                             << id << chDoubleQuote;
  650.             id = ((IDOM_Entity *)toWrite)->getSystemId();
  651.             if (id != 0)
  652.                 *gFormatter << XMLFormatter::NoEscapes << gSystem
  653.                             << id << chDoubleQuote;
  654.             id = ((IDOM_Entity *)toWrite)->getNotationName();
  655.             if (id != 0)
  656.                 *gFormatter << XMLFormatter::NoEscapes << gNotation
  657.                             << id << chDoubleQuote;
  658.             *gFormatter << XMLFormatter::NoEscapes << chCloseAngle << chLF;
  659.             break;
  660.         }
  661.         default:
  662.             cerr << "Unrecognized node type = "
  663.                  << (long)toWrite->getNodeType() << endl;
  664.     }
  665.     return target;
  666. }
  667. // ---------------------------------------------------------------------------
  668. //  ostream << XMLCh *
  669. //
  670. //  Stream out a DOM string. Doing this requires that we first transcode
  671. //  to char * form in the default code page for the system
  672. // ---------------------------------------------------------------------------
  673. ostream& operator<< (ostream& target, const XMLCh *s)
  674. {
  675.     char *p = XMLString::transcode(s);
  676.     target << p;
  677.     delete [] p;
  678.     return target;
  679. }