source: icXML/icXML-devel/samples/src/DOMPrint/DOMPrint.cpp @ 2733

Last change on this file since 2733 was 2733, checked in by cameron, 6 years ago

More path fixes.

File size: 21.9 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: DOMPrint.cpp 833057 2009-11-05 15:25:10Z borisk $
20 */
21
22// ---------------------------------------------------------------------------
23//  This sample program invokes the XercesDOMParser to build a DOM tree for
24//  the specified input file. It then invokes DOMLSSerializer::write() to
25//  serialize the resultant DOM tree back to XML stream.
26//
27//  Note:
28//  Application needs to provide its own implementation of
29//                 DOMErrorHandler (in this sample, the DOMPrintErrorHandler),
30//                 if it would like to receive notification from the serializer
31//                 in the case any error occurs during the serialization.
32//
33//  Application needs to provide its own implementation of
34//                 DOMLSSerializerFilter (in this sample, the DOMPrintFilter),
35//                 if it would like to filter out certain part of the DOM
36//                 representation, but must be aware that thus may render the
37//                 resultant XML stream invalid.
38//
39//  Application may choose any combination of characters as the
40//                 end of line sequence to be used in the resultant XML stream,
41//                 but must be aware that thus may render the resultant XML
42//                 stream ill formed.
43//
44//  Application may choose a particular encoding name in which
45//                 the output XML stream would be, but must be aware that if
46//                 characters, unrepresentable in the encoding specified, appearing
47//                 in markups, may force the serializer to terminate serialization
48//                 prematurely, and thus no complete serialization would be done.
49//
50//  Application shall query the serializer first, before set any
51//           feature/mode(true, false), or be ready to catch exception if this
52//           feature/mode is not supported by the serializer.
53//
54//  Application needs to clean up the filter, error handler and
55//                 format target objects created for the serialization.
56//
57//   Limitations:
58//      1.  The encoding="xxx" clause in the XML header should reflect
59//          the system local code page, but does not.
60//      2.  Cases where the XML data contains characters that can not
61//          be represented in the system local code page are not handled.
62//
63// ---------------------------------------------------------------------------
64
65
66// ---------------------------------------------------------------------------
67//  Includes
68// ---------------------------------------------------------------------------
69#include <icxercesc/util/PlatformUtils.hpp>
70
71#include <xercesc/dom/DOM.hpp>
72
73#include <xercesc/framework/StdOutFormatTarget.hpp>
74#include <xercesc/framework/LocalFileFormatTarget.hpp>
75#include <xercesc/parsers/XercesDOMParser.hpp>
76#include <xercesc/util/XMLUni.hpp>
77
78#include "DOMTreeErrorReporter.hpp"
79#include "DOMPrintFilter.hpp"
80#include "DOMPrintErrorHandler.hpp"
81#include <xercesc/util/OutOfMemoryException.hpp>
82
83#include <string.h>
84#include <stdlib.h>
85
86// ---------------------------------------------------------------------------
87//  Local data
88//
89//  gXmlFile
90//      The path to the file to parser. Set via command line.
91//
92//  gDoNamespaces
93//      Indicates whether namespace processing should be done.
94//
95//  gDoSchema
96//      Indicates whether schema processing should be done.
97//
98//  gSchemaFullChecking
99//      Indicates whether full schema constraint checking should be done.
100//
101//  gDoCreate
102//      Indicates whether entity reference nodes needs to be created or not
103//      Defaults to false
104//
105//  gOutputEncoding
106//      The encoding we are to output in. If not set on the command line,
107//      then it is defaults to the encoding of the input XML file.
108//
109//  gSplitCdataSections
110//      Indicates whether split-cdata-sections is to be enabled or not.
111//
112//  gDiscardDefaultContent
113//      Indicates whether default content is discarded or not.
114//
115//  gUseFilter
116//      Indicates if user wants to plug in the DOMPrintFilter.
117//
118//  gValScheme
119//      Indicates what validation scheme to use. It defaults to 'auto', but
120//      can be set via the -v= command.
121//
122// ---------------------------------------------------------------------------
123static char*                    gXmlFile               = 0;
124static bool                     gDoNamespaces          = false;
125static bool                     gDoSchema              = false;
126static bool                     gSchemaFullChecking    = false;
127static bool                     gDoCreate              = false;
128
129static char*                    goutputfile            = 0;
130static char*                    gXPathExpression       = 0;
131
132// options for DOMLSSerializer's features
133static XMLCh*                   gOutputEncoding        = 0;
134
135static bool                     gSplitCdataSections    = true;
136static bool                     gDiscardDefaultContent = true;
137static bool                     gUseFilter             = false;
138static bool                     gFormatPrettyPrint     = false;
139static bool                     gWriteBOM              = false;
140
141static XercesDOMParser::ValSchemes    gValScheme       = XercesDOMParser::Val_Auto;
142
143
144//      Prototypes for internally used functions
145void usage();
146
147
148// ---------------------------------------------------------------------------
149//
150//  Usage()
151//
152// ---------------------------------------------------------------------------
153void usage()
154{
155    XERCES_STD_QUALIFIER cout << "\nUsage:\n"
156            "    DOMPrint [options] <XML file>\n\n"
157            "This program invokes the DOM parser, and builds the DOM tree.\n"
158            "It then asks the DOMLSSerializer to serialize the DOM tree.\n"
159            "Options:\n"
160            "    -e          create entity reference nodes. Default is no expansion.\n"
161            "    -v=xxx      Validation scheme [always | never | auto*].\n"
162            "    -n          Enable namespace processing. Default is off.\n"
163            "    -s          Enable schema processing. Default is off.\n"
164            "    -f          Enable full schema constraint checking. Defaults is off.\n"
165            "    -wenc=XXX   Use a particular encoding for output. Default is\n"
166            "                the same encoding as the input XML file. UTF-8 if\n"
167            "                input XML file has not XML declaration.\n"
168            "    -wfile=xxx  Write to a file instead of stdout.\n"
169            "    -wscs=xxx   Enable/Disable split-cdata-sections.      Default on\n"
170            "    -wddc=xxx   Enable/Disable discard-default-content.   Default on\n"
171            "    -wflt=xxx   Enable/Disable filtering.                 Default off\n"
172            "    -wfpp=xxx   Enable/Disable format-pretty-print.       Default off\n"
173            "    -wbom=xxx   Enable/Disable write Byte-Order-Mark      Default off\n"
174            "    -xpath=xxx  Prints only the nodes matching the given XPath.\n"
175            "    -?          Show this help.\n\n"
176            "  * = Default if not provided explicitly.\n\n"
177            "The parser has intrinsic support for the following encodings:\n"
178            "    UTF-8, US-ASCII, ISO8859-1, UTF-16[BL]E, UCS-4[BL]E,\n"
179            "    WINDOWS-1252, IBM1140, IBM037, IBM1047.\n"
180          <<  XERCES_STD_QUALIFIER endl;
181}
182
183// ---------------------------------------------------------------------------
184//
185//  main
186//
187// ---------------------------------------------------------------------------
188int main(int argC, char* argV[])
189{
190    int retval = 0;
191
192    // Initialize the XML4C2 system
193    try
194    {
195        XMLPlatformUtils::Initialize();
196    }
197
198    catch(const XMLException &toCatch)
199    {
200        XERCES_STD_QUALIFIER cerr << "Error during Xerces-c Initialization.\n"
201             << "  Exception message:"
202             << StrX(toCatch.getMessage()) << XERCES_STD_QUALIFIER endl;
203        return 1;
204    }
205
206    // Check command line and extract arguments.
207    if (argC < 2)
208    {
209        usage();
210        XMLPlatformUtils::Terminate();
211        return 1;
212    }
213
214    // See if non validating dom parser configuration is requested.
215    int parmInd;
216    for (parmInd = 1; parmInd < argC; parmInd++)
217    {
218        // Break out on first parm not starting with a dash
219        if (argV[parmInd][0] != '-')
220            break;
221
222        // Watch for special case help request
223        if (!strcmp(argV[parmInd], "-?"))
224        {
225            usage();
226            XMLPlatformUtils::Terminate();
227            return 2;
228        }
229         else if (!strncmp(argV[parmInd], "-v=", 3)
230              ||  !strncmp(argV[parmInd], "-V=", 3))
231        {
232            const char* const parm = &argV[parmInd][3];
233
234            if (!strcmp(parm, "never"))
235                gValScheme = XercesDOMParser::Val_Never;
236            else if (!strcmp(parm, "auto"))
237                gValScheme = XercesDOMParser::Val_Auto;
238            else if (!strcmp(parm, "always"))
239                gValScheme = XercesDOMParser::Val_Always;
240            else
241            {
242                XERCES_STD_QUALIFIER cerr << "Unknown -v= value: " << parm << XERCES_STD_QUALIFIER endl;
243                XMLPlatformUtils::Terminate();
244                return 2;
245            }
246        }
247         else if (!strcmp(argV[parmInd], "-n")
248              ||  !strcmp(argV[parmInd], "-N"))
249        {
250            gDoNamespaces = true;
251        }
252         else if (!strcmp(argV[parmInd], "-s")
253              ||  !strcmp(argV[parmInd], "-S"))
254        {
255            gDoSchema = true;
256        }
257         else if (!strcmp(argV[parmInd], "-f")
258              ||  !strcmp(argV[parmInd], "-F"))
259        {
260            gSchemaFullChecking = true;
261        }
262         else if (!strcmp(argV[parmInd], "-e")
263              ||  !strcmp(argV[parmInd], "-E"))
264        {
265            gDoCreate = true;
266        }
267         else if (!strncmp(argV[parmInd], "-wenc=", 6))
268        {
269             // Get out the encoding name
270             gOutputEncoding = XMLString::transcode( &(argV[parmInd][6]) );
271        }
272         else if (!strncmp(argV[parmInd], "-wfile=", 7))
273        {
274             goutputfile =  &(argV[parmInd][7]);
275        }
276         else if (!strncmp(argV[parmInd], "-wddc=", 6))
277        {
278            const char* const parm = &argV[parmInd][6];
279
280            if (!strcmp(parm, "on"))
281                                gDiscardDefaultContent = true;
282            else if (!strcmp(parm, "off"))
283                                gDiscardDefaultContent = false;
284            else
285            {
286                XERCES_STD_QUALIFIER cerr << "Unknown -wddc= value: " << parm << XERCES_STD_QUALIFIER endl;
287                XMLPlatformUtils::Terminate();
288                return 2;
289            }
290
291        }
292         else if (!strncmp(argV[parmInd], "-wscs=", 6))
293        {
294            const char* const parm = &argV[parmInd][6];
295
296            if (!strcmp(parm, "on"))
297                                gSplitCdataSections = true;
298                        else if (!strcmp(parm, "off"))
299                                gSplitCdataSections = false;
300            else
301            {
302                XERCES_STD_QUALIFIER cerr << "Unknown -wscs= value: " << parm << XERCES_STD_QUALIFIER endl;
303                XMLPlatformUtils::Terminate();
304                return 2;
305            }
306        }
307         else if (!strncmp(argV[parmInd], "-wflt=", 6))
308        {
309            const char* const parm = &argV[parmInd][6];
310
311            if (!strcmp(parm, "on"))
312                                gUseFilter = true;
313                        else if (!strcmp(parm, "off"))
314                                gUseFilter = false;
315            else
316            {
317                XERCES_STD_QUALIFIER cerr << "Unknown -wflt= value: " << parm << XERCES_STD_QUALIFIER endl;
318                XMLPlatformUtils::Terminate();
319                return 2;
320            }
321        }
322         else if (!strncmp(argV[parmInd], "-wfpp=", 6))
323        {
324            const char* const parm = &argV[parmInd][6];
325
326            if (!strcmp(parm, "on"))
327                                gFormatPrettyPrint = true;
328                        else if (!strcmp(parm, "off"))
329                                gFormatPrettyPrint = false;
330            else
331            {
332                XERCES_STD_QUALIFIER cerr << "Unknown -wfpp= value: " << parm << XERCES_STD_QUALIFIER endl;
333                XMLPlatformUtils::Terminate();
334                return 2;
335            }
336        }
337         else if (!strncmp(argV[parmInd], "-wbom=", 6))
338        {
339            const char* const parm = &argV[parmInd][6];
340
341            if (!strcmp(parm, "on"))
342                gWriteBOM = true;
343            else if (!strcmp(parm, "off"))
344                gWriteBOM = false;
345            else
346            {
347                XERCES_STD_QUALIFIER cerr << "Unknown -wbom= value: " << parm << XERCES_STD_QUALIFIER endl;
348                XMLPlatformUtils::Terminate();
349                return 2;
350            }
351        }
352         else if (!strncmp(argV[parmInd], "-xpath=", 7))
353        {
354             gXPathExpression = &(argV[parmInd][7]);
355        }
356         else
357        {
358            XERCES_STD_QUALIFIER cerr << "Unknown option '" << argV[parmInd]
359                 << "', ignoring it.\n" << XERCES_STD_QUALIFIER endl;
360        }
361    }
362
363    //
364    //  And now we have to have only one parameter left and it must be
365    //  the file name.
366    //
367    if (parmInd + 1 != argC)
368    {
369        usage();
370        XMLPlatformUtils::Terminate();
371        return 1;
372    }
373    gXmlFile = argV[parmInd];
374
375    //
376    //  Create our parser, then attach an error handler to the parser.
377    //  The parser will call back to methods of the ErrorHandler if it
378    //  discovers errors during the course of parsing the XML document.
379    //
380    XercesDOMParser *parser = new XercesDOMParser;
381    parser->setValidationScheme(gValScheme);
382    parser->setDoNamespaces(gDoNamespaces);
383    parser->setDoSchema(gDoSchema);
384    parser->setHandleMultipleImports (true);
385    parser->setValidationSchemaFullChecking(gSchemaFullChecking);
386    parser->setCreateEntityReferenceNodes(gDoCreate);
387
388    DOMTreeErrorReporter *errReporter = new DOMTreeErrorReporter();
389    parser->setErrorHandler(errReporter);
390
391    //
392    //  Parse the XML file, catching any XML exceptions that might propogate
393    //  out of it.
394    //
395    bool errorsOccured = false;
396    try
397    {
398        parser->parse(gXmlFile);
399    }
400    catch (const OutOfMemoryException&)
401    {
402        XERCES_STD_QUALIFIER cerr << "OutOfMemoryException" << XERCES_STD_QUALIFIER endl;
403        errorsOccured = true;
404    }
405    catch (const XMLException& e)
406    {
407        XERCES_STD_QUALIFIER cerr << "An error occurred during parsing\n   Message: "
408             << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
409        errorsOccured = true;
410    }
411
412    catch (const DOMException& e)
413    {
414        const unsigned int maxChars = 2047;
415        XMLCh errText[maxChars + 1];
416
417        XERCES_STD_QUALIFIER cerr << "\nDOM Error during parsing: '" << gXmlFile << "'\n"
418             << "DOMException code is:  " << e.code << XERCES_STD_QUALIFIER endl;
419
420        if (DOMImplementation::loadDOMExceptionMsg(e.code, errText, maxChars))
421             XERCES_STD_QUALIFIER cerr << "Message is: " << StrX(errText) << XERCES_STD_QUALIFIER endl;
422
423        errorsOccured = true;
424    }
425
426    catch (...)
427    {
428        XERCES_STD_QUALIFIER cerr << "An error occurred during parsing\n " << XERCES_STD_QUALIFIER endl;
429        errorsOccured = true;
430    }
431
432    // If the parse was successful, output the document data from the DOM tree
433    if (!errorsOccured && !errReporter->getSawErrors())
434    {
435        DOMPrintFilter   *myFilter = 0;
436
437        try
438        {
439            // get a serializer, an instance of DOMLSSerializer
440            XMLCh tempStr[3] = {chLatin_L, chLatin_S, chNull};
441            DOMImplementation *impl          = DOMImplementationRegistry::getDOMImplementation(tempStr);
442            DOMLSSerializer   *theSerializer = ((DOMImplementationLS*)impl)->createLSSerializer();
443            DOMLSOutput       *theOutputDesc = ((DOMImplementationLS*)impl)->createLSOutput();
444
445            // set user specified output encoding
446            theOutputDesc->setEncoding(gOutputEncoding);
447
448            // plug in user's own filter
449            if (gUseFilter)
450            {
451                // even we say to show attribute, but the DOMLSSerializer
452                // will not show attribute nodes to the filter as
453                // the specs explicitly says that DOMLSSerializer shall
454                // NOT show attributes to DOMLSSerializerFilter.
455                //
456                // so DOMNodeFilter::SHOW_ATTRIBUTE has no effect.
457                // same DOMNodeFilter::SHOW_DOCUMENT_TYPE, no effect.
458                //
459                myFilter = new DOMPrintFilter(DOMNodeFilter::SHOW_ELEMENT   |
460                                              DOMNodeFilter::SHOW_ATTRIBUTE |
461                                              DOMNodeFilter::SHOW_DOCUMENT_TYPE);
462                theSerializer->setFilter(myFilter);
463            }
464
465            // plug in user's own error handler
466            DOMErrorHandler *myErrorHandler = new DOMPrintErrorHandler();
467            DOMConfiguration* serializerConfig=theSerializer->getDomConfig();
468            serializerConfig->setParameter(XMLUni::fgDOMErrorHandler, myErrorHandler);
469
470            // set feature if the serializer supports the feature/mode
471            if (serializerConfig->canSetParameter(XMLUni::fgDOMWRTSplitCdataSections, gSplitCdataSections))
472                serializerConfig->setParameter(XMLUni::fgDOMWRTSplitCdataSections, gSplitCdataSections);
473
474            if (serializerConfig->canSetParameter(XMLUni::fgDOMWRTDiscardDefaultContent, gDiscardDefaultContent))
475                serializerConfig->setParameter(XMLUni::fgDOMWRTDiscardDefaultContent, gDiscardDefaultContent);
476
477            if (serializerConfig->canSetParameter(XMLUni::fgDOMWRTFormatPrettyPrint, gFormatPrettyPrint))
478                serializerConfig->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, gFormatPrettyPrint);
479
480            if (serializerConfig->canSetParameter(XMLUni::fgDOMWRTBOM, gWriteBOM))
481                serializerConfig->setParameter(XMLUni::fgDOMWRTBOM, gWriteBOM);
482
483            //
484            // Plug in a format target to receive the resultant
485            // XML stream from the serializer.
486            //
487            // StdOutFormatTarget prints the resultant XML stream
488            // to stdout once it receives any thing from the serializer.
489            //
490            XMLFormatTarget *myFormTarget;
491            if (goutputfile)
492                myFormTarget=new LocalFileFormatTarget(goutputfile);
493            else
494                myFormTarget=new StdOutFormatTarget();
495            theOutputDesc->setByteStream(myFormTarget);
496
497            // get the DOM representation
498            DOMDocument *doc = parser->getDocument();
499
500            //
501            // do the serialization through DOMLSSerializer::write();
502            //
503            if(gXPathExpression!=NULL)
504            {
505                XMLCh* xpathStr=XMLString::transcode(gXPathExpression);
506                DOMElement* root = doc->getDocumentElement();
507                try
508                {
509                    DOMXPathNSResolver* resolver=doc->createNSResolver(root);
510                    DOMXPathResult* result=doc->evaluate(
511                      xpathStr,
512                      root,
513                      resolver,
514                      DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
515                      NULL);
516
517                    XMLSize_t nLength = result->getSnapshotLength();
518                    for(XMLSize_t i = 0; i < nLength; i++)
519                    {
520                      result->snapshotItem(i);
521                      theSerializer->write(result->getNodeValue(), theOutputDesc);
522                    }
523
524                    result->release();
525                    resolver->release ();
526                }
527                catch(const DOMXPathException& e)
528                {
529                    XERCES_STD_QUALIFIER cerr << "An error occurred during processing of the XPath expression. Msg is:"
530                        << XERCES_STD_QUALIFIER endl
531                        << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
532                    retval = 4;
533                }
534                catch(const DOMException& e)
535                {
536                    XERCES_STD_QUALIFIER cerr << "An error occurred during processing of the XPath expression. Msg is:"
537                        << XERCES_STD_QUALIFIER endl
538                        << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
539                    retval = 4;
540                }
541                XMLString::release(&xpathStr);
542            }
543            else
544                theSerializer->write(doc, theOutputDesc);
545
546            theOutputDesc->release();
547            theSerializer->release();
548
549            //
550            // Filter, formatTarget and error handler
551            // are NOT owned by the serializer.
552            //
553            delete myFormTarget;
554            delete myErrorHandler;
555
556            if (gUseFilter)
557                delete myFilter;
558
559        }
560        catch (const OutOfMemoryException&)
561        {
562            XERCES_STD_QUALIFIER cerr << "OutOfMemoryException" << XERCES_STD_QUALIFIER endl;
563            retval = 5;
564        }
565        catch (XMLException& e)
566        {
567            XERCES_STD_QUALIFIER cerr << "An error occurred during creation of output transcoder. Msg is:"
568                << XERCES_STD_QUALIFIER endl
569                << StrX(e.getMessage()) << XERCES_STD_QUALIFIER endl;
570            retval = 4;
571        }
572
573    }
574    else
575        retval = 4;
576
577    //
578    //  Clean up the error handler. The parser does not adopt handlers
579    //  since they could be many objects or one object installed for multiple
580    //  handlers.
581    //
582    delete errReporter;
583
584    //
585    //  Delete the parser itself.  Must be done prior to calling Terminate, below.
586    //
587    delete parser;
588
589    XMLString::release(&gOutputEncoding);
590
591    // And call the termination method
592    XMLPlatformUtils::Terminate();
593
594    return retval;
595}
Note: See TracBrowser for help on using the repository browser.