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

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-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) 1999, 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: DOMPrint.cpp,v 1.35 2001/10/19 18:47:28 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 <dom/DOM_DOMException.hpp>
  82. #include <parsers/DOMParser.hpp>
  83. #include <dom/DOM.hpp>
  84. #include "DOMTreeErrorReporter.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, chNull
  102. };
  103. static const XMLCh  gXMLDecl2[] =
  104. {
  105.         chDoubleQuote, chSpace, chLatin_e, chLatin_n, chLatin_c
  106.     ,   chLatin_o, chLatin_d, chLatin_i, chLatin_n, chLatin_g, chEqual
  107.     ,   chDoubleQuote, chNull
  108. };
  109. static const XMLCh  gXMLDecl3[] =
  110. {
  111.         chDoubleQuote, chSpace, chLatin_s, chLatin_t, chLatin_a
  112.     ,   chLatin_n, chLatin_d, chLatin_a, chLatin_l, chLatin_o
  113.     ,   chLatin_n, chLatin_e, chEqual, chDoubleQuote, chNull
  114. };
  115. static const XMLCh  gXMLDecl4[] =
  116. {
  117.         chDoubleQuote, chQuestion, chCloseAngle
  118.     ,   chLF, chNull
  119. };
  120. static const XMLCh  gStartCDATA[] =
  121. {
  122.         chOpenAngle, chBang, chOpenSquare, chLatin_C, chLatin_D,
  123.         chLatin_A, chLatin_T, chLatin_A, chOpenSquare, chNull
  124. };
  125. static const XMLCh  gEndCDATA[] =
  126. {
  127.     chCloseSquare, chCloseSquare, chCloseAngle, chNull
  128. };
  129. static const XMLCh  gStartComment[] =
  130. {
  131.     chOpenAngle, chBang, chDash, chDash, chNull
  132. };
  133. static const XMLCh  gEndComment[] =
  134. {
  135.     chDash, chDash, chCloseAngle, chNull
  136. };
  137. static const XMLCh  gStartDoctype[] =
  138. {
  139.     chOpenAngle, chBang, chLatin_D, chLatin_O, chLatin_C, chLatin_T,
  140.     chLatin_Y, chLatin_P, chLatin_E, chSpace, chNull
  141. };
  142. static const XMLCh  gPublic[] =
  143. {
  144.     chLatin_P, chLatin_U, chLatin_B, chLatin_L, chLatin_I,
  145.     chLatin_C, chSpace, chDoubleQuote, chNull
  146. };
  147. static const XMLCh  gSystem[] =
  148. {
  149.     chLatin_S, chLatin_Y, chLatin_S, chLatin_T, chLatin_E,
  150.     chLatin_M, chSpace, chDoubleQuote, chNull
  151. };
  152. static const XMLCh  gStartEntity[] =
  153. {
  154.     chOpenAngle, chBang, chLatin_E, chLatin_N, chLatin_T, chLatin_I,
  155.     chLatin_T, chLatin_Y, chSpace, chNull
  156. };
  157. static const XMLCh  gNotation[] =
  158. {
  159.     chLatin_N, chLatin_D, chLatin_A, chLatin_T, chLatin_A,
  160.     chSpace, chDoubleQuote, chNull
  161. };
  162. // ---------------------------------------------------------------------------
  163. //  Local classes
  164. // ---------------------------------------------------------------------------
  165. class DOMPrintFormatTarget : public XMLFormatTarget
  166. {
  167. public:
  168.     DOMPrintFormatTarget()  {};
  169.     ~DOMPrintFormatTarget() {};
  170.     // -----------------------------------------------------------------------
  171.     //  Implementations of the format target interface
  172.     // -----------------------------------------------------------------------
  173.     void writeChars(const   XMLByte* const  toWrite,
  174.                     const   unsigned int    count,
  175.                             XMLFormatter * const formatter)
  176.     {
  177.         // Surprisingly, Solaris was the only platform on which
  178.         // required the char* cast to print out the string correctly.
  179.         // Without the cast, it was printing the pointer value in hex.
  180.         // Quite annoying, considering every other platform printed
  181.         // the string with the explicit cast to char* below.
  182.         cout.write((char *) toWrite, (int) count);
  183.     };
  184. private:
  185.     // -----------------------------------------------------------------------
  186.     //  Unimplemented methods.
  187.     // -----------------------------------------------------------------------
  188.     DOMPrintFormatTarget(const DOMPrintFormatTarget& other);
  189.     void operator=(const DOMPrintFormatTarget& rhs);
  190. };
  191. // ---------------------------------------------------------------------------
  192. //  Local data
  193. //
  194. //  gXmlFile
  195. //      The path to the file to parser. Set via command line.
  196. //
  197. //  gDoNamespaces
  198. //      Indicates whether namespace processing should be done.
  199. //
  200. //  gDoSchema
  201. //      Indicates whether schema processing should be done.
  202. //
  203. //  gSchemaFullChecking
  204. //      Indicates whether full schema constraint checking should be done.
  205. //
  206. //  gDoCreate
  207. //      Indicates whether entity reference nodes needs to be created or not
  208. //      Defaults to false
  209. //
  210. //  gEncodingName
  211. //      The encoding we are to output in. If not set on the command line,
  212. //      then it is defaults to the encoding of the input XML file.
  213. //
  214. //  gValScheme
  215. //      Indicates what validation scheme to use. It defaults to 'auto', but
  216. //      can be set via the -v= command.
  217. //
  218. // ---------------------------------------------------------------------------
  219. static char*                    gXmlFile               = 0;
  220. static bool                     gDoNamespaces          = false;
  221. static bool                     gDoSchema              = false;
  222. static bool                     gSchemaFullChecking    = false;
  223. static bool                     gDoCreate              = false;
  224. static XMLCh*                   gEncodingName          = 0;
  225. static XMLFormatter::UnRepFlags gUnRepFlags            = XMLFormatter::UnRep_CharRef;
  226. static DOMParser::ValSchemes    gValScheme             = DOMParser::Val_Auto;
  227. static XMLFormatter*            gFormatter             = 0;
  228. // ---------------------------------------------------------------------------
  229. //  Forward references
  230. // ---------------------------------------------------------------------------
  231. void     usage();
  232. ostream& operator<<(ostream& target, const DOMString& toWrite);
  233. ostream& operator<<(ostream& target, DOM_Node& toWrite);
  234. XMLFormatter& operator<< (XMLFormatter& strm, const DOMString& s);
  235. // ---------------------------------------------------------------------------
  236. //
  237. //  Usage()
  238. //
  239. // ---------------------------------------------------------------------------
  240. void usage()
  241. {
  242.     cout << "nUsage:n"
  243.             "    DOMPrint [options] <XML file>nn"
  244.             "This program invokes the DOM parser, and builds the DOM tree.n"
  245.             "It then traverses the DOM tree and prints the contents of then"
  246.             "tree for the specified XML file.nn"
  247.             "Options:n"
  248.             "    -e          create entity reference nodes. Default is no expansion.n"
  249.             "    -u=xxx      Handle unrepresentable chars [fail | rep | ref*].n"
  250.             "    -v=xxx      Validation scheme [always | never | auto*].n"
  251.             "    -n          Enable namespace processing. Default is off.n"
  252.             "    -s          Enable schema processing. Default is off.n"
  253.             "    -f          Enable full schema constraint checking. Defaults to off.n"
  254.             "    -x=XXX      Use a particular encoding for output. Default isn"
  255.             "                the same encoding as the input XML file. UTF-8 ifn"
  256.             "                input XML file has not XML declaration.n"
  257.       "    -?          Show this help.nn"
  258.             "  * = Default if not provided explicitly.nn"
  259.             "The parser has intrinsic support for the following encodings:n"
  260.             "    UTF-8, USASCII, ISO8859-1, UTF-16[BL]E, UCS-4[BL]E,n"
  261.             "    WINDOWS-1252, IBM1140, IBM037.n"
  262.           <<  endl;
  263. }
  264. // ---------------------------------------------------------------------------
  265. //
  266. //  main
  267. //
  268. // ---------------------------------------------------------------------------
  269. int main(int argC, char* argV[])
  270. {
  271.     int retval = 0;
  272.     // Initialize the XML4C2 system
  273.     try
  274.     {
  275.         XMLPlatformUtils::Initialize();
  276.     }
  277.     catch(const XMLException& toCatch)
  278.     {
  279.         cerr << "Error during Xerces-c Initialization.n"
  280.              << "  Exception message:"
  281.              << DOMString(toCatch.getMessage()) << endl;
  282.         return 1;
  283.     }
  284.     // Check command line and extract arguments.
  285.     if (argC < 2)
  286.     {
  287.         usage();
  288.         XMLPlatformUtils::Terminate();
  289.         return 1;
  290.     }
  291.     // See if non validating dom parser configuration is requested.
  292.     int parmInd;
  293.     for (parmInd = 1; parmInd < argC; parmInd++)
  294.     {
  295.         // Break out on first parm not starting with a dash
  296.         if (argV[parmInd][0] != '-')
  297.             break;
  298.         // Watch for special case help request
  299.         if (!strcmp(argV[parmInd], "-?"))
  300.         {
  301.             usage();
  302.             XMLPlatformUtils::Terminate();
  303.             return 2;
  304.         }
  305.          else if (!strncmp(argV[parmInd], "-v=", 3)
  306.               ||  !strncmp(argV[parmInd], "-V=", 3))
  307.         {
  308.             const char* const parm = &argV[parmInd][3];
  309.             if (!strcmp(parm, "never"))
  310.                 gValScheme = DOMParser::Val_Never;
  311.             else if (!strcmp(parm, "auto"))
  312.                 gValScheme = DOMParser::Val_Auto;
  313.             else if (!strcmp(parm, "always"))
  314.                 gValScheme = DOMParser::Val_Always;
  315.             else
  316.             {
  317.                 cerr << "Unknown -v= value: " << parm << endl;
  318.                 XMLPlatformUtils::Terminate();
  319.                 return 2;
  320.             }
  321.         }
  322.          else if (!strcmp(argV[parmInd], "-n")
  323.               ||  !strcmp(argV[parmInd], "-N"))
  324.         {
  325.             gDoNamespaces = true;
  326.         }
  327.          else if (!strcmp(argV[parmInd], "-s")
  328.               ||  !strcmp(argV[parmInd], "-S"))
  329.         {
  330.             gDoSchema = true;
  331.         }
  332.          else if (!strcmp(argV[parmInd], "-f")
  333.               ||  !strcmp(argV[parmInd], "-F"))
  334.         {
  335.             gSchemaFullChecking = true;
  336.         }
  337.          else if (!strcmp(argV[parmInd], "-e")
  338.               ||  !strcmp(argV[parmInd], "-E"))
  339.         {
  340.             gDoCreate = true;
  341.         }
  342.          else if (!strncmp(argV[parmInd], "-x=", 3)
  343.               ||  !strncmp(argV[parmInd], "-X=", 3))
  344.         {
  345.              // Get out the encoding name
  346.              gEncodingName = XMLString::transcode( &(argV[parmInd][3]) );
  347.         }
  348.          else if (!strncmp(argV[parmInd], "-u=", 3)
  349.               ||  !strncmp(argV[parmInd], "-U=", 3))
  350.         {
  351.             const char* const parm = &argV[parmInd][3];
  352.             if (!strcmp(parm, "fail"))
  353.                 gUnRepFlags = XMLFormatter::UnRep_Fail;
  354.             else if (!strcmp(parm, "rep"))
  355.                 gUnRepFlags = XMLFormatter::UnRep_Replace;
  356.             else if (!strcmp(parm, "ref"))
  357.                 gUnRepFlags = XMLFormatter::UnRep_CharRef;
  358.             else
  359.             {
  360.                 cerr << "Unknown -u= value: " << parm << endl;
  361.                 XMLPlatformUtils::Terminate();
  362.                 return 2;
  363.             }
  364.         }
  365.         //  else if (!strcmp(argV[parmInd], "-NoEscape"))
  366.         // {
  367.         //     gDoEscapes = false;
  368.         // }
  369.          else
  370.         {
  371.             cerr << "Unknown option '" << argV[parmInd]
  372.                  << "', ignoring it.n" << endl;
  373.         }
  374.     }
  375.     //
  376.     //  And now we have to have only one parameter left and it must be
  377.     //  the file name.
  378.     //
  379.     if (parmInd + 1 != argC)
  380.     {
  381.         usage();
  382.         XMLPlatformUtils::Terminate();
  383.         return 1;
  384.     }
  385.     gXmlFile = argV[parmInd];
  386.     //
  387.     //  Create our parser, then attach an error handler to the parser.
  388.     //  The parser will call back to methods of the ErrorHandler if it
  389.     //  discovers errors during the course of parsing the XML document.
  390.     //
  391.     DOMParser *parser = new DOMParser;
  392.     parser->setValidationScheme(gValScheme);
  393.     parser->setDoNamespaces(gDoNamespaces);
  394.     parser->setDoSchema(gDoSchema);
  395.     parser->setValidationSchemaFullChecking(gSchemaFullChecking);
  396.     DOMTreeErrorReporter *errReporter = new DOMTreeErrorReporter();
  397.     parser->setErrorHandler(errReporter);
  398.     parser->setCreateEntityReferenceNodes(gDoCreate);
  399.     parser->setToCreateXMLDeclTypeNode(true);
  400.     //
  401.     //  Parse the XML file, catching any XML exceptions that might propogate
  402.     //  out of it.
  403.     //
  404.     bool errorsOccured = false;
  405.     try
  406.     {
  407.         parser->parse(gXmlFile);
  408.         int errorCount = parser->getErrorCount();
  409.         if (errorCount > 0)
  410.             errorsOccured = true;
  411.     }
  412.     catch (const XMLException& e)
  413.     {
  414.         cerr << "An error occured during parsingn   Message: "
  415.              << DOMString(e.getMessage()) << endl;
  416.         errorsOccured = true;
  417.     }
  418.     catch (const DOM_DOMException& e)
  419.     {
  420.        cerr << "A DOM error occured during parsingn   DOMException code: "
  421.              << e.code << endl;
  422.         errorsOccured = true;
  423.     }
  424.     catch (...)
  425.     {
  426.         cerr << "An error occured during parsingn " << endl;
  427.         errorsOccured = true;
  428.     }
  429.     // If the parse was successful, output the document data from the DOM tree
  430.     if (!errorsOccured && !errReporter->getSawErrors())
  431.     {
  432.         DOM_Node doc = parser->getDocument();
  433.         DOMPrintFormatTarget* formatTarget = new DOMPrintFormatTarget();
  434.         if (gEncodingName == 0)
  435.         {
  436.             DOMString encNameStr("UTF-8");
  437.             DOM_Node aNode = doc.getFirstChild();
  438.             if (aNode.getNodeType() == DOM_Node::XML_DECL_NODE)
  439.             {
  440.                 DOMString aStr = ((DOM_XMLDecl &)aNode).getEncoding();
  441.                 if (aStr != "")
  442.                 {
  443.                     encNameStr = aStr;
  444.                 }
  445.             }
  446.             unsigned int lent = encNameStr.length();
  447.             gEncodingName = new XMLCh[lent + 1];
  448.             XMLString::copyNString(gEncodingName, encNameStr.rawBuffer(), lent);
  449.             gEncodingName[lent] = 0;
  450.         }
  451.         try
  452.         {
  453.             gFormatter = new XMLFormatter(gEncodingName, formatTarget,
  454.                                           XMLFormatter::NoEscapes, gUnRepFlags);
  455.             cout << doc;
  456.             *gFormatter << chLF; // add linefeed in requested output encoding
  457.             cout << flush;
  458.         }
  459.         catch (XMLException& e)
  460.         {
  461.             cerr << "An error occurred during creation of output transcoder. Msg is:"
  462.                  << endl
  463.                  << DOMString(e.getMessage()) << endl;
  464.             retval = 4;
  465.         }
  466.         delete formatTarget;
  467.         delete gFormatter;
  468.     }
  469.     else
  470.         retval = 4;
  471.     delete [] gEncodingName;
  472.     //
  473.     //  Clean up the error handler. The parser does not adopt handlers
  474.     //  since they could be many objects or one object installed for multiple
  475.     //  handlers.
  476.     //
  477.     delete errReporter;
  478.     //
  479.     //  Delete the parser itself.  Must be done prior to calling Terminate, below.
  480.     //
  481.     delete parser;
  482.     // And call the termination method
  483.     XMLPlatformUtils::Terminate();
  484.     // DomMemDebug().print();
  485.     //
  486.     //  The DOM document and its contents are reference counted, and need
  487.     //  no explicit deletion.
  488.     //
  489.     return retval;
  490. }
  491. // ---------------------------------------------------------------------------
  492. //  ostream << DOM_Node
  493. //
  494. //  Stream out a DOM node, and, recursively, all of its children. This
  495. //  function is the heart of writing a DOM tree out as XML source. Give it
  496. //  a document node and it will do the whole thing.
  497. // ---------------------------------------------------------------------------
  498. ostream& operator<<(ostream& target, DOM_Node& toWrite)
  499. {
  500.     // Get the name and value out for convenience
  501.     DOMString   nodeName = toWrite.getNodeName();
  502.     DOMString   nodeValue = toWrite.getNodeValue();
  503.     unsigned long lent = nodeValue.length();
  504.     switch (toWrite.getNodeType())
  505.     {
  506.         case DOM_Node::TEXT_NODE:
  507.         {
  508.             gFormatter->formatBuf(nodeValue.rawBuffer(),
  509.                                   lent, XMLFormatter::CharEscapes);
  510.             break;
  511.         }
  512.         case DOM_Node::PROCESSING_INSTRUCTION_NODE :
  513.         {
  514.             *gFormatter << XMLFormatter::NoEscapes << gStartPI  << nodeName;
  515.             if (lent > 0)
  516.             {
  517.                 *gFormatter << chSpace << nodeValue;
  518.             }
  519.             *gFormatter << XMLFormatter::NoEscapes << gEndPI;
  520.             break;
  521.         }
  522.         case DOM_Node::DOCUMENT_NODE :
  523.         {
  524.             DOM_Node child = toWrite.getFirstChild();
  525.             while( child != 0)
  526.             {
  527.                 target << child;
  528.                 // add linefeed in requested output encoding
  529.                 *gFormatter << chLF;
  530.                 target << flush;
  531.                 child = child.getNextSibling();
  532.             }
  533.             break;
  534.         }
  535.         case DOM_Node::ELEMENT_NODE :
  536.         {
  537.             // The name has to be representable without any escapes
  538.             *gFormatter  << XMLFormatter::NoEscapes
  539.                          << chOpenAngle << nodeName;
  540.             // Output the element start tag.
  541.             // Output any attributes on this element
  542.             DOM_NamedNodeMap attributes = toWrite.getAttributes();
  543.             int attrCount = attributes.getLength();
  544.             for (int i = 0; i < attrCount; i++)
  545.             {
  546.                 DOM_Node  attribute = attributes.item(i);
  547.                 //
  548.                 //  Again the name has to be completely representable. But the
  549.                 //  attribute can have refs and requires the attribute style
  550.                 //  escaping.
  551.                 //
  552.                 *gFormatter  << XMLFormatter::NoEscapes
  553.                              << chSpace << attribute.getNodeName()
  554.                              << chEqual << chDoubleQuote
  555.                              << XMLFormatter::AttrEscapes
  556.                              << attribute.getNodeValue()
  557.                              << XMLFormatter::NoEscapes
  558.                              << chDoubleQuote;
  559.             }
  560.             //
  561.             //  Test for the presence of children, which includes both
  562.             //  text content and nested elements.
  563.             //
  564.             DOM_Node child = toWrite.getFirstChild();
  565.             if (child != 0)
  566.             {
  567.                 // There are children. Close start-tag, and output children.
  568.                 // No escapes are legal here
  569.                 *gFormatter << XMLFormatter::NoEscapes << chCloseAngle;
  570.                 while( child != 0)
  571.                 {
  572.                     target << child;
  573.                     child = child.getNextSibling();
  574.                 }
  575.                 //
  576.                 // Done with children.  Output the end tag.
  577.                 //
  578.                 *gFormatter << XMLFormatter::NoEscapes << gEndElement
  579.                             << nodeName << chCloseAngle;
  580.             }
  581.             else
  582.             {
  583.                 //
  584.                 //  There were no children. Output the short form close of
  585.                 //  the element start tag, making it an empty-element tag.
  586.                 //
  587.                 *gFormatter << XMLFormatter::NoEscapes << chForwardSlash << chCloseAngle;
  588.             }
  589.             break;
  590.         }
  591.         case DOM_Node::ENTITY_REFERENCE_NODE:
  592.             {
  593.                 DOM_Node child;
  594. #if 0
  595.                 for (child = toWrite.getFirstChild();
  596.                 child != 0;
  597.                 child = child.getNextSibling())
  598.                 {
  599.                     target << child;
  600.                 }
  601. #else
  602.                 //
  603.                 // Instead of printing the refernece tree
  604.                 // we'd output the actual text as it appeared in the xml file.
  605.                 // This would be the case when -e option was chosen
  606.                 //
  607.                     *gFormatter << XMLFormatter::NoEscapes << chAmpersand
  608.                         << nodeName << chSemiColon;
  609. #endif
  610.                 break;
  611.             }
  612.         case DOM_Node::CDATA_SECTION_NODE:
  613.             {
  614.             *gFormatter << XMLFormatter::NoEscapes << gStartCDATA
  615.                         << nodeValue << gEndCDATA;
  616.             break;
  617.         }
  618.         case DOM_Node::COMMENT_NODE:
  619.         {
  620.             *gFormatter << XMLFormatter::NoEscapes << gStartComment
  621.                         << nodeValue << gEndComment;
  622.             break;
  623.         }
  624.         case DOM_Node::DOCUMENT_TYPE_NODE:
  625.         {
  626.             DOM_DocumentType doctype = (DOM_DocumentType &)toWrite;;
  627.             *gFormatter << XMLFormatter::NoEscapes  << gStartDoctype
  628.                         << nodeName;
  629.             DOMString id = doctype.getPublicId();
  630.             if (id != 0)
  631.             {
  632.                 *gFormatter << XMLFormatter::NoEscapes << chSpace << gPublic
  633.                     << id << chDoubleQuote;
  634.                 id = doctype.getSystemId();
  635.                 if (id != 0)
  636.                 {
  637.                     *gFormatter << XMLFormatter::NoEscapes << chSpace
  638.                        << chDoubleQuote << id << chDoubleQuote;
  639.                 }
  640.             }
  641.             else
  642.             {
  643.                 id = doctype.getSystemId();
  644.                 if (id != 0)
  645.                 {
  646.                     *gFormatter << XMLFormatter::NoEscapes << chSpace << gSystem
  647.                         << id << chDoubleQuote;
  648.                 }
  649.             }
  650.             id = doctype.getInternalSubset();
  651.             if (id !=0)
  652.                 *gFormatter << XMLFormatter::NoEscapes << chOpenSquare
  653.                             << id << chCloseSquare;
  654.             *gFormatter << XMLFormatter::NoEscapes << chCloseAngle;
  655.             break;
  656.         }
  657.         case DOM_Node::ENTITY_NODE:
  658.         {
  659.             *gFormatter << XMLFormatter::NoEscapes << gStartEntity
  660.                         << nodeName;
  661.             DOMString id = ((DOM_Entity &)toWrite).getPublicId();
  662.             if (id != 0)
  663.                 *gFormatter << XMLFormatter::NoEscapes << gPublic
  664.                             << id << chDoubleQuote;
  665.             id = ((DOM_Entity &)toWrite).getSystemId();
  666.             if (id != 0)
  667.                 *gFormatter << XMLFormatter::NoEscapes << gSystem
  668.                             << id << chDoubleQuote;
  669.             id = ((DOM_Entity &)toWrite).getNotationName();
  670.             if (id != 0)
  671.                 *gFormatter << XMLFormatter::NoEscapes << gNotation
  672.                             << id << chDoubleQuote;
  673.             *gFormatter << XMLFormatter::NoEscapes << chCloseAngle << chLF;
  674.             break;
  675.         }
  676.         case DOM_Node::XML_DECL_NODE:
  677.         {
  678.             DOMString  str;
  679.             *gFormatter << gXMLDecl1 << ((DOM_XMLDecl &)toWrite).getVersion();
  680.             *gFormatter << gXMLDecl2 << gEncodingName;
  681.             str = ((DOM_XMLDecl &)toWrite).getStandalone();
  682.             if (str != 0)
  683.                 *gFormatter << gXMLDecl3 << str;
  684.             *gFormatter << gXMLDecl4;
  685.             break;
  686.         }
  687.         default:
  688.             cerr << "Unrecognized node type = "
  689.                  << (long)toWrite.getNodeType() << endl;
  690.     }
  691.     return target;
  692. }
  693. // ---------------------------------------------------------------------------
  694. //  ostream << DOMString
  695. //
  696. //  Stream out a DOM string. Doing this requires that we first transcode
  697. //  to char * form in the default code page for the system
  698. // ---------------------------------------------------------------------------
  699. ostream& operator<< (ostream& target, const DOMString& s)
  700. {
  701.     char *p = s.transcode();
  702.     target << p;
  703.     delete [] p;
  704.     return target;
  705. }
  706. XMLFormatter& operator<< (XMLFormatter& strm, const DOMString& s)
  707. {
  708.     unsigned int lent = s.length();
  709. if (lent <= 0)
  710. return strm;
  711.     XMLCh*  buf = new XMLCh[lent + 1];
  712.     XMLString::copyNString(buf, s.rawBuffer(), lent);
  713.     buf[lent] = 0;
  714.     strm << buf;
  715.     delete [] buf;
  716.     return strm;
  717. }