Skip Headers

Oracle9i Application Developer's Guide - XML
Release 1 (9.0.1)

Part Number A88894-01
Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Go to previous page Go to next page

26
Using XML Parser for C++

This chapter contains the following sections:

Accessing XML Parser for C++

The XML Parser for C++ is provided with Oracle9i and is also available for download from the OTN site: http://otn.oracle.com/tech/xml.

It is located at $ORACLE_HOME/xdk/cpp/parser.

XML Parser for C++ Features

readme.html in the root directory of the software archive contains release specific information including bug fixes and API additions.

XML Parser for C++ will check if an XML document is well-formed, and optionally validate it against a DTD. The parser will construct an object tree which can be accessed via a DOM interface or operate serially via a SAX interface.

You can post questions, comments, or bug reports to the XML Discussion Forum at http://otn.oracle.com.

Specifications

See Appendix F, "XDK for C++: Specifications and Cheat Sheet" for a list of XML Parser for C++ specifications and methods.

See Also:

 

Memory Allocation

The memory callback functions memcb may be used if you wish to use your own memory allocation. If they are used, all of the functions should be specified.

The memory allocated for parameters passed to the SAX callbacks or for nodes and data stored with the DOM parse tree will not be freed until one of the following is done:

Thread Safety

If threads are forked off somewhere in the midst of the init-parse-term sequence of calls, you will get unpredictable behavior and results.

Data Types Index

Table 26-1 lists the datatypes used in XML Parser for C++.

Table 26-1 Datatypes Used in XML Parser for C++  
DataType  Description 

oratext 

String pointer  

xmlctx 

Master XML context  

xmlmemcb 

Memory callback structure (optional)  

xmlsaxcb 

SAX callback structure (SAX only)  

ub4 

32-bit (or larger) unsigned integer  

uword 

Native unsigned integer  

Error Message Files

Error message files are provided in the mesg/ subdirectory. The messages files also exist in the $ORACLE_HOME/oracore/mesg directory. You may set the environment variable ORA_XML_MESG to point to the absolute path of the mesg/ subdirectory although this not required.

Validation Modes

Available validation modes are described in Chapter 20, "Using XML Parser for Java", "Oracle XML Parsers Support Four Validation Modes" .

XML Parser for C++ Usage

Figure 26-1 illustrates the XML Parser for C++ functionality.

  1. The parsing process begins with the xmlinit() method.

  2. The XML input can be either an XML file or string buffer. This inputs the following methods:

    • XMLParser.xmlparse() if the input is an XML file

    • XMLParser.xmlparseBuffer() if the input is a string buffer

  3. DOM or SAX API

    DOM: If you are using the DOM interface, include the following steps:

    • The XMLParser.xmlparse() or .xmlparserBuffer() method calls .getDocument Element(). If no other DOM methods are being applied, you can invoke .xmlterm().

    • This optionally calls other DOM methods if required. These are typically Node class methods or print methods. It outputs the DOM document.

    • If complete, the process invokes .xmlterm()

    • You can optionally first invoke .xmlclean() to clean up any data structure created during the parse process. You would then call .xmlterm()

    SAX: If you are using the SAX interface, include the following steps:

    • Process the results of the parser from .xmlparse() or .xmlparseBuffer() via callback methods.

    • Register the callback methods

  4. Optionally, use .xmlclean() to clean up the memory and structures used during a parse, and go to Step 5. or return to Step 2.

  5. Terminate the parsing process with .xmlterm()

Parser Calling Sequence

The sequence of calls to the parser can be any of the following:

Figure 26-1 XML Parser for C++ (DOM and SAX Interfaces) Usage


Text description of adxml050.gif follows
Text description of the illustration adxml050.gif

XML Parser for C++ XSLT (DOM Interface) Usage

Figure 26-2 shows the XML Parser for C++ XSLT functionality for the DOM interface.

  1. There are two inputs to XMLParser.xmlparse():

    • The Stylesheet to be applied to the XML document

    • XML document

    The output of XMLParser.xmlparse(), the parsed stylesheet and parsed XML document, are sent to the XSLProcess.xslprocess() method for processing.

  2. XMLParser.xmlinit() initializes the XSLT processing. XMLParser. xmlinit() also initializes the xslprocess() result

  3. XSLProcess.xslProcess() optionally calls other methods, such as print methods. You can see the list of available methods either on OTN or in Oracle9i XML Reference.

  4. The resultant document (XML, HTML, VML, and so on) is typically sent to an application for further processing.

  5. The application terminates the XSLT process by declaring XMLParser.xmlterm(), for the XML document, stylesheet, and final result.

XML Parser for C XSLT functionality is illustrated with the following examples:

Figure 26-2 Parser for C++: XSL-T Functionality (DOM Interface) Usage


Text description of adxml057.gif follows
Text description of the illustration adxml057.gif

Default Behavior

The following is the XML Parser for C++ default behavior:

DOM and SAX APIs

Oracle XML parser for C++ checks if an XML document is well-formed, and optionally validates it against a DTD. The parser constructs an object tree which can be accessed via one of the following interfaces:

These two XML APIs:

Tree-based APIs are useful for a wide range of applications, but they often put a great strain on system resources, especially if the document is large (under very controlled circumstances, it is possible to construct the tree in a lazy fashion to avoid some of this problem). Furthermore, some applications need to build their own, different data trees, and it is very inefficient to build a tree of parse nodes, only to map it onto a new tree.

In both of these cases, an event-based API provides a simpler, lower-level access to an XML document: you can parse documents much larger than your available system memory, and you can construct your own data structures using your callback event handlers.

Using the SAX API

To use SAX, an xmlsaxcb structure is initialized with function pointers and passed to the xmlinit() call. A pointer to a user-defined context structure can also be included. That context pointer will be passed to each SAX function.

SAX Callback Structure

The SAX callback structure:

typedef struct
{
 sword (*startDocument)(void *ctx);
 sword (*endDocument)(void *ctx);
 sword (*startElement)(void *ctx, const oratext *name, 
             const struct xmlarray *attrs);
 sword (*endElement)(void *ctx, const oratext *name);
 sword (*characters)(void *ctx, const oratext *ch, size_t len);
 sword (*ignorableWhitespace)(void *ctx, const oratext *ch, size_t len);
 sword (*processingInstruction)(void *ctx, const oratext *target,
             const oratext *data);
 sword (*notationDecl)(void *ctx, const oratext *name,
             const oratext *publicId, const oratext *systemId);
 sword (*unparsedEntityDecl)(void *ctx, const oratext *name, 
             const oratext *publicId,
             const oratext *systemId, const oratext *notationName);
 sword (*nsStartElement)(void *ctx, const oratext *qname,
             const oratext *local, const oratext *nsp,
             const struct xmlnodes *attrs);
} xmlsaxcb;

Using the DOM API

See "XML Parser for C++ Example 6: C++ -- DOMSample.cpp" .

Invoking XML Parser for C++

XML Parser for C++ can be invoked in two ways:

Command Line Usage

The XML Parser for C++ can be called as an executable by invoking bin/xml

Table 26-2 lists the command line options.

Table 26-2 XML Parser for C++: Command Line Options
Option  Description 

-c 

Conformance check only, no validation 

-e encoding 

Specify input file encoding 

-h 

Help - show this usage help 

-n 

Number - DOM traverse and report number of elements 

-p 

Print document and DTD structures after parse 

-x 

Exercise SAX interface and print document 

-v 

Version - display parser version then exit 

-w 

Whitespace - preserve all whitespace  

Writing C++ Code to Use Supplied APIs

XML Parser for C++ can also be invoked by writing code to use the supplied APIs. The code must be compiled using the headers in the include/ subdirectory and linked against the libraries in the lib/ subdirectory. Please see the Makefile in the sample/ subdirectory for full details of how to build your program.

Using the Sample Files Included with Your Software

$ORACLE_HOME/xdk/cpp/parser/sample/ directory contains several XML applications to illustrate how to use the XML Parser for C++ with the DOM and SAX interfaces.

Table 26-3 lists the sample files in sample/ directory.

Table 26-3 XML Parser for C++ sample/ Files
sample/ File Name  Description 

DOMNamespace.cpp 

Source for DOMNamespace program 

DOMNamespace.std 

Expected output from DOMNamespace 

DOMSample.cpp 

Source for DOMSample program 

DOMSample.std 

Expected output from DOMSample 

FullDOM.c  

Sample usage of DOM interface 

FullDOM.std 

Expected output from FullDOM 

Make.bat 

Batch file to build sample executables 

Makefile 

Makefile for sample programs 

NSExample.xml 

Sample XML file using namespaces 

SAXNamespace.cpp 

Source for SAXNamespace program 

SAXNamespace.std 

Expected output from SAXNamespace 

SAXSample.cpp 

Source for SAXSample program 

SAXSample.std 

Expected output from SAXSample 

XSLSample.cpp 

Source for XSLSample program 

XSLSample.std 

Expected output from XSLSample 

class.xml  

XML file that may be used with XSLSample 

iden.xsl  

Stylesheet that may be used with XSLSample 

cleo.xml 

XML version of Shakespeare's play 

Running the XML Parser for C++ Sample Programs

Building the Sample programs

Change directories to ..sample/ and read the README file. This will explain how to build the sample programs according to your platform.

Sample Programs

Table 26-4 lists the programs built by the sample files in sample/.

Table 26-4 XML Parser for C++, Sample Programs Built in sample/
Built Program  Description 

SAXSample 

A sample application using SAX APIs. Prints out all speakers in each scene, i.e. all the unique SPEAKER elements within each SCENE element. 

DOMSample [speaker] 

A sample application using DOM APIs. Prints all speeches made by the given speaker. If no speaker is specified, "Soothsayer" is used. Note that major characters have uppercase names (e.g. "CLEOPATRA"), whereas minor characters have capitalized names (e.g. "Attendant"). See the output of SAXSample. 

SAXNamespace 

A sample application using Namespace extensions to SAX API; prints out all elements and attributes of NSExample.xml along with full namespace information. 

DOMNamespace 

Same as SAXNamespace except using DOM interface. 

FullDOM 

Sample usage of full DOM interface. Exercises all the calls, but does nothing too exciting. 

XSLSample <xmlfile> <xsl ss> 

Sample usage of XSL processor. It takes two filenames as input, the XML file and the XSL stylesheet. Note: If you redirect stdout of this program to a file, you may encounter some missing output, depending on your environment. 

XML Parser for C++ Example 1: XML -- class.xml

class.xml is an XML file that inputs XSLSample.cpp.

<?xml version = "1.0"?>
<!DOCTYPE course [
<!ELEMENT course (Name, Dept, Instructor, Student)>
<!ELEMENT Name (#PCDATA)>
<!ELEMENT Dept (#PCDATA)>
<!ELEMENT Instructor (Name)>
<!ELEMENT Student (Name*)>
]>
<course>
<Name>Calculus</Name>
<Dept>Math</Dept>
<Instructor>
<Name>Jim Green</Name>
</Instructor>
<Student>
<Name>Jack</Name>
<Name>Mary</Name>
<Name>Paul</Name>
</Student>
</course>

XML Parser for C++ Example 2: XML -- cleo.xml

This XML example inputs DOMSample.cpp and SAXSample.cpp.

<?xml version="1.0"?>
<!DOCTYPE PLAY [
    <!ELEMENT PLAY     (TITLE, PERSONAE, SCNDESCR, PLAYSUBT, INDUCT?,
						 PROLOGUE?, ACT+, EPILOGUE?)>
    <!ELEMENT TITLE    (#PCDATA)>
    <!ELEMENT FM       (P+)>
    <!ELEMENT P        (#PCDATA)>
    <!ELEMENT PERSONAE (TITLE, (PERSONA | PGROUP)+)>
    <!ELEMENT PGROUP   (PERSONA+, GRPDESCR)>
    <!ELEMENT PERSONA  (#PCDATA)>
    <!ELEMENT GRPDESCR (#PCDATA)>
    <!ELEMENT SCNDESCR (#PCDATA)>
    <!ELEMENT PLAYSUBT (#PCDATA)>
    <!ELEMENT INDUCT   (TITLE, SUBTITLE*, (SCENE+|(SPEECH|STAGEDIR|SUBHEAD)+))>
    <!ELEMENT ACT      (TITLE, SUBTITLE*, PROLOGUE?, SCENE+, EPILOGUE?)>
    <!ELEMENT SCENE    (TITLE, SUBTITLE*, (SPEECH | STAGEDIR | SUBHEAD)+)>
    <!ELEMENT PROLOGUE (TITLE, SUBTITLE*, (STAGEDIR | SPEECH)+)>
    <!ELEMENT EPILOGUE (TITLE, SUBTITLE*, (STAGEDIR | SPEECH)+)>
    <!ELEMENT SPEECH   (SPEAKER+, (LINE | STAGEDIR | SUBHEAD)+)>
    <!ELEMENT SPEAKER  (#PCDATA)>
    <!ELEMENT LINE     (#PCDATA | STAGEDIR)*>
    <!ELEMENT STAGEDIR (#PCDATA)>
    <!ELEMENT SUBTITLE (#PCDATA)>
    <!ELEMENT SUBHEAD  (#PCDATA)>
]>

<PLAY>
<TITLE>The Tragedy of Antony and Cleopatra</TITLE>

<PERSONAE>
<TITLE>Dramatis Personae</TITLE>


<PGROUP>
<PERSONA>MARK ANTONY</PERSONA>
<PERSONA>OCTAVIUS CAESAR</PERSONA>
<PERSONA>M. AEMILIUS LEPIDUS</PERSONA>
<GRPDESCR>triumvirs.</GRPDESCR>
</PGROUP>

<PERSONA>SEXTUS POMPEIUS</PERSONA>

<PGROUP>
<PERSONA>DOMITIUS ENOBARBUS</PERSONA>
<PERSONA>VENTIDIUS</PERSONA>
<PERSONA>EROS</PERSONA>
<PERSONA>SCARUS</PERSONA>
<PERSONA>DERCETAS</PERSONA>
<PERSONA>DEMETRIUS</PERSONA>
<PERSONA>PHILO</PERSONA>
<GRPDESCR>friends to Antony.</GRPDESCR>
</PGROUP>


<PGROUP>
<PERSONA>MECAENAS</PERSONA>
<PERSONA>AGRIPPA</PERSONA>
<PERSONA>DOLABELLA</PERSONA>
<PERSONA>PROCULEIUS</PERSONA>
<PERSONA>THYREUS</PERSONA>
<PERSONA>GALLUS</PERSONA>
<PERSONA>MENAS</PERSONA>
<GRPDESCR>friends to Caesar.</GRPDESCR>
</PGROUP>
...
...
...
<SPEECH>
<SPEAKER>First Guard</SPEAKER>
<LINE>This is an aspic's trail: and these fig-leaves</LINE>
<LINE>Have slime upon them, such as the aspic leaves</LINE>
<LINE>Upon the caves of Nile.</LINE>
</SPEECH>

<SPEECH>
<SPEAKER>OCTAVIUS CAESAR</SPEAKER>
<LINE>Most probable</LINE>
<LINE>That so she died; for her physician tells me</LINE>
<LINE>She hath pursued conclusions infinite</LINE>
<LINE>Of easy ways to die. Take up her bed;</LINE>
<LINE>And bear her women from the monument:</LINE>
<LINE>She shall be buried by her Antony:</LINE>
<LINE>No grave upon the earth shall clip in it</LINE>
<LINE>A pair so famous. High events as these</LINE>
<LINE>Strike those that make them; and their story is</LINE>
<LINE>No less in pity than his glory which</LINE>
<LINE>Brought them to be lamented. Our army shall</LINE>
<LINE>In solemn show attend this funeral;</LINE>
<LINE>And then to Rome. Come, Dolabella, see</LINE>
<LINE>High order in this great solemnity.</LINE>
</SPEECH>

<STAGEDIR>Exeunt</STAGEDIR>
</SCENE>
</ACT>
</PLAY>

XML Parser for C++ Example 3: XSL -- iden.xsl

This example stylesheet can be used to input XSLSample.cpp.

<?xml version="1.0"?> 
<!-- Identity transformation -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
                
  <xsl:template match="*|@*|comment()|processing-instruction()|text()">
      <xsl:copy>
          <xsl:apply-templates 
select="*|@*|comment()|processing-instruction()|text()"/>
      </xsl:copy>
  </xsl:template>
     
</xsl:stylesheet>

XML Parser for C++ Example 4: XML -- FullDOM.xml (DTD)

This example DTD file inputs FullDOM.cpp.

<!DOCTYPE doc [
    <!ELEMENT p (#PCDATA)>
    <!ATTLIST p xml:space (preserve|default) 'preserve'>
    <!NOTATION notation1 SYSTEM "file.txt">
    <!NOTATION notation2 PUBLIC "some notation">
    <!ELEMENT doc (p*)>
    <!ENTITY example "<p>An ampersand (&#38;#38;) may be escaped
numerically (&#38;#38;#38;) or with a general entity
(&amp;amp;).</p>">
]>
<doc xml:lang="foo">&example;</doc>

XML Parser for C++ Example 5: XML -- NSExample.xml

The following example file, NSExample.xml, uses namespaces.

<!DOCTYPE doc [
<!ELEMENT doc (child*)>
<!ATTLIST doc xmlns:nsprefix CDATA #IMPLIED>
<!ATTLIST doc xmlns CDATA #IMPLIED>
<!ATTLIST doc nsprefix:a1 CDATA #IMPLIED>
<!ELEMENT child (#PCDATA)>
]>
<doc nsprefix:a1 = "v1" xmlns="http://www.w3c.org" 
xmlns:nsprefix="http://www.oracle.com">
<child>
This element inherits the default Namespace of doc.
</child>
</doc>

XML Parser for C++ Example 6: C++ -- DOMSample.cpp

This example contains the C++ source code for DOMSample.cpp.

// Copyright (c) Oracle Corporation 1999, 2000. All Rights Reserved.

///////////////////////////////////////////////////////////////////////////////
// NAME
//   DOMSample.cpp
//
// DESCRIPTION
//   Sample usage of C++ XML parser via DOM interface
//
// PUBLIC FUNCTION(S)
//
// PRIVATE FUNCTION(S)
//
// NOTES
//   none
///////////////////////////////////////////////////////////////////////////////

#include <iostream.h>
#include <string.h>

#ifndef ORAXMLDOM_ORACLE
# include <oraxmldom.h>
#endif

#define DOCUMENT	"cleo.xml"
#define DEFAULT_SPEAKER	"Soothsayer"

void dump(Node *node);
void dumpspeech(Node *node);

char *speaker;
char *act, *scene;
uword n_speech;

int main(int argc, char **argv)
{
    XMLParser   parser;
    ub4         flags;
    uword       ecode;
    flags = XML_FLAG_VALIDATE | XML_FLAG_DISCARD_WHITESPACE;

    cout << "XML C++ DOM sample\n";

    speaker = (argc > 1) ? argv[1] : DEFAULT_SPEAKER;

    cout << "Initializing XML package...\n";

    if (ecode = parser.xmlinit())
    {
        cout << "Failed to initialize XML parser, error " << ecode;
        return 1;
    }

    cout << "Parsing '" << DOCUMENT << "'...\n";
    cout.flush();
    if (ecode = parser.xmlparse((oratext *) DOCUMENT, (oratext *) 0, flags))
	return 1;

    cout << "Dumping " << speaker << " speeches...\n";
    cout.flush();
    cout << "-----------------------------------------------------------\n";
    act = scene = "";
    n_speech = 0;
    dump(parser.getDocumentElement());

    (void) parser.xmlterm();	// terminate LPX package

    return 0;
}

void dump(Node *node)
{
    Node *title, *speak;
    char *name, *who;
    uword i, n_nodes;

    name = (char *) node->getName();
    if (!strcmp((char *) name, "ACT"))
    {
title = node->getFirstChild();
act = (char *) title->getFirstChild()->getValue();
    }
    else if (!strcmp((char *) name, "SCENE"))
    {
title = node->getFirstChild();
scene = (char *) title->getFirstChild()->getValue();
    }
    else if (!strcmp((char *) name, "SPEECH"))
    {
speak = node->getFirstChild();
who = (char *) speak->getFirstChild()->getValue();
if (!strcmp(who, speaker))
    dumpspeech(node);
    }

    if (node->hasChildNodes())
    {
n_nodes = node->numChildNodes();
for (i = 0; i < n_nodes; i++)
    dump(node->getChildNode(i));
    }
}

// <SPEECH>
// <SPEAKER>Soothsayer</SPEAKER>
// <LINE>Your will?</LINE>
// </SPEECH>

// <SPEECH>
// <SPEAKER>CLEOPATRA</SPEAKER>
// <LINE><STAGEDIR>Aside to DOMITIUS ENOBARBUS</STAGEDIR>  What means 
this?</LINE>
// </SPEECH>

void dumpspeech(Node *node)
{
    Node    *kid, *part, *partkid;
    uword    i, j, n_node, n_part;
    oratext *partname, *partval;

    if (n_speech++)
cout << "\n";
    cout << act << ", " << scene << "\n";
    n_node = node->numChildNodes();
    for (i = 0; i < n_node; i++)	// skip speaker
    {
kid = node->getChildNode(i);	// line #i
if (!strcmp((char *) kid->getName(), "LINE"))
{
    n_part = kid->numChildNodes();
    for (j = 0; j < n_part; j++)
    {
part = kid->getChildNode(j);
if (part->getType() == TEXT_NODE)
    cout << "    " << (char *) part->getValue() << "\n";
else
{
    partname = part->getName();
    partval = part->getFirstChild()->getValue();
    if (!strcmp((char *) partname, "STAGEDIR"))
cout << "    [" << (char *) partval << "]\n";
    else
cout << "    {" << (char *) partval << "}\n";
}
    }
}
    }
    cout.flush();
}

// end of DOMSample.c

XML Parser for C++ Example 7: C++ -- DOMSample.std

DOMSample.std shows the expected output from DOMSample.cpp.

XML C++ DOM sample
Initializing XML package...
Parsing 'cleo.xml'...
Dumping Soothsayer speeches...
-----------------------------------------------------------
ACT I, SCENE II.  The same. Another room.
    Your will?

ACT I, SCENE II.  The same. Another room.
    In nature's infinite book of secrecy
    A little I can read.

ACT I, SCENE II.  The same. Another room.
    I make not, but foresee.

ACT I, SCENE II.  The same. Another room.
    You shall be yet far fairer than you are.

ACT I, SCENE II.  The same. Another room.
    You shall be more beloving than beloved.

ACT I, SCENE II.  The same. Another room.
    You shall outlive the lady whom you serve.

ACT I, SCENE II.  The same. Another room.
    You have seen and proved a fairer former fortune
    Than that which is to approach.

ACT I, SCENE II.  The same. Another room.
    If every of your wishes had a womb.
    And fertile every wish, a million.

ACT I, SCENE II.  The same. Another room.
    Your fortunes are alike.

ACT I, SCENE II.  The same. Another room.
    I have said.

ACT II, SCENE III.  The same. OCTAVIUS CAESAR's house.
    Would I had never come from thence, nor you Thither!

ACT II, SCENE III.  The same. OCTAVIUS CAESAR's house.
    I see it in
    My motion, have it not in my tongue: but yet
    Hie you to Egypt again.

ACT II, SCENE III.  The same. OCTAVIUS CAESAR's house.
    Caesar's.
    Therefore, O Antony, stay not by his side:
    Thy demon, that's thy spirit which keeps thee, is
    Noble, courageous high, unmatchable,
    Where Caesar's is not; but, near him, thy angel
    Becomes a fear, as being o'erpower'd: therefore
    Make space enough between you.

ACT II, SCENE III.  The same. OCTAVIUS CAESAR's house.
    To none but thee; no more, but when to thee.
    If thou dost play with him at any game,
    Thou art sure to lose; and, of that natural luck,
    He beats thee 'gainst the odds: thy lustre thickens,
    When he shines by: I say again, thy spirit
    Is all afraid to govern thee near him;
    But, he away, 'tis noble.

XML Parser for C++ Example 8: C++ -- SAXSample.cpp

This example contains the C++ source code for SAXSample.cpp.

// Copyright (c) Oracle Corporation 1999, 2000. All Rights Reserved.

///////////////////////////////////////////////////////////////////////////////
// NAME
//   SAXSample.cpp
//
// DESCRIPTION
//   Sample usage of C++ XML parser via SAX interface
//
// PUBLIC FUNCTION(S)
//
// PRIVATE FUNCTION(S)
//
// NOTES
//   none
///////////////////////////////////////////////////////////////////////////////

#include <iostream.h>
#include <string.h>

#ifndef ORAXMLDOM_ORACLE
# include <oraxmldom.h>
#endif

#define DOCUMENT	"cleo.xml"
#define MAX_STRING	128
#define MAX_SPEAKER	20

oratext  elem[MAX_STRING], last_elem[MAX_STRING];
uword    n_speaker;
oratext *speakers[MAX_SPEAKER];
size_t   speakerlen[MAX_SPEAKER];

/* SAX callback functions */
 
sword startDocument(void *ctx);
sword endDocument(void *ctx);
sword startElement(void *ctx, const oratext *name,
		   const struct xmlnodes *attrs);
sword endElement(void *ctx, const oratext *name);
sword characters(void *ctx, const oratext *ch, size_t len);
 
xmlsaxcb saxcb = {
    startDocument,
    endDocument,
    startElement,
    endElement,
    characters
};

int main()
{
    XMLParser   parser;
    ub4         flags;
    uword       ecode;
    flags = XML_FLAG_VALIDATE | XML_FLAG_DISCARD_WHITESPACE;

    cout << "XML C++ SAX sample\n";

    cout << "Initializing XML package...\n";

    if (ecode = parser.xmlinit((oratext *) 0,
// encoding
  (void (*)(void *, const oratext *, ub4)) 0,
  (void *) 0,
// msghdlr ctx
  (xmlsaxcb *) &saxcb))
// SAX callback
    {
    cout << "Failed to initialize XML parser, error " << ecode;
    return 1;
    }

    cout << "Parsing '" << DOCUMENT << "' and showing speakers by scene...\n";
    cout.flush();
    if (ecode = parser.xmlparse((oratext *) DOCUMENT, (oratext *) 0, flags))
return 1;

    (void) parser.xmlterm();
// terminate LPX package

    return 0;
}

sword startDocument(void *ctx)
{
    cout << "startDocument\n";
    return 0;
}

sword endDocument(void *ctx)
{
    cout << "endDocument\n";
    return 0;
}

sword startElement(void *ctx, const oratext *name,
   const struct xmlnodes *attrs)
{
    strcpy((char *) last_elem, (char *) elem);
    strcpy((char *) elem, (char *) name);
    return 0;
}

sword endElement(void *ctx, const oratext *name)
{
    uword i;

    if (!strcmp((char *) name, "SCENE"))
    {
for (i = 0; i < n_speaker; i++)
{
    cout << "    ";
    cout.write(speakers[i], speakerlen[i]);
    cout << "\n";
}
    }
    return 0;
}

sword characters(void *ctx, const oratext *ch, size_t len)
{
    uword i;

    if (!strcmp((char *) elem, "TITLE"))
    {
if (!strcmp((char *) last_elem, "ACT"))
{
    cout << "\n--- ";
    cout.write(ch, len);
    cout << " ---\n\n";
}
else if (!strcmp((char *) last_elem, "SCENE"))
{
    n_speaker = 0;
    cout << "  ";
    cout.write(ch, len);
    cout << "\n";
}
    }
    else if (!strcmp((char *) elem, "SPEAKER"))
    {
if (n_speaker < MAX_SPEAKER)
{
    for (i = 0; i < n_speaker; i++)
if ((len == speakerlen[i]) && !strncmp((char *) speakers[i],
(char *) ch, len))
    break;
    if (!n_speaker || (i == n_speaker))
    {
speakers[n_speaker] = (oratext *) ch;
speakerlen[n_speaker++] = len;
    }
}
    }
    return 0;
}

// end of SAXSample.cc

XML Parser for C++ Example 9: C++ -- SAXSample.std

SAXSample.std shows the expected output from SAXSample.cpp.

XML C++ SAX sample
Initializing XML package...
Parsing 'cleo.xml' and showing speakers by scene...
startDocument

--- ACT I ---

  SCENE I.  Alexandria. A room in CLEOPATRA's palace.
    PHILO
    CLEOPATRA
    MARK ANTONY
    Attendant
    DEMETRIUS
  SCENE II.  The same. Another room.
    CHARMIAN
    ALEXAS
    Soothsayer
    DOMITIUS ENOBARBUS
    IRAS
    CLEOPATRA
    Messenger
    MARK ANTONY
    First Attendant
    Second Attendant
    Second Messenger
  SCENE III.  The same. Another room.
    CLEOPATRA
    CHARMIAN
    MARK ANTONY
  SCENE IV.  Rome. OCTAVIUS CAESAR's house.
    OCTAVIUS CAESAR
    LEPIDUS
    Messenger
  SCENE V.  Alexandria. CLEOPATRA's palace.
    CLEOPATRA
    CHARMIAN
    MARDIAN
    ALEXAS

--- ACT II ---
 
...
...
--- ACT V ---
  SCENE I.  Alexandria. OCTAVIUS CAESAR's camp.
    OCTAVIUS CAESAR
    DOLABELLA
    DERCETAS
    AGRIPPA
    MECAENAS
    Egyptian
    PROCULEIUS
    All
  SCENE II.  Alexandria. A room in the monument.
    CLEOPATRA
    PROCULEIUS
    GALLUS
    IRAS
    CHARMIAN
    DOLABELLA
    OCTAVIUS CAESAR
    SELEUCUS
    Guard
    Clown
    First Guard
    Second Guard
endDocument

XML Parser for C++ Example 10: C++ -- DOMNamespace.cpp

This example contains the C++ source code for DOMNamespace.cpp.

// Copyright (c) Oracle Corporation 1999, 2000. All Rights Reserved.

//////////////////////////////////////////////////////////////////////////////
// NAME
//   DOMNamespace.cpp
//
// DESCRIPTION
//   This file demonstates a simple use of the parser and Namespace
//   extensions to the DOM APIs. 
//
//   The XML file that is given to the application is parsed and the
//   elements and attributes in the document are printed.
//
// PUBLIC FUNCTION(S)
//
// PRIVATE FUNCTION(S)
//
// NOTES
//   none
//////////////////////////////////////////////////////////////////////////////

#include <iostream.h>

#ifndef ORAXMLDOM_ORACLE
# include <oraxmldom.h>
#endif

#define DOCUMENT         "NSExample.xml"

void dump(Node *node);
void dumpattrs(Node *node);

//
// main
//

int main()
{
    XMLParser   parser;
    ub4         flags;
    uword       ecode;
    flags = XML_FLAG_VALIDATE | XML_FLAG_DISCARD_WHITESPACE;

    cout << "\nXML C++ DOM Namespace\n";
    cout << "Initializing XML package...\n";
    if (ecode = parser.xmlinit())
    {
        cout << "Failed to initialize XML parser, error " << ecode;
        return 1;
    }

    cout << "Parsing '" << DOCUMENT << "'...\n";
    cout.flush();
    if (ecode = parser.xmlparse((oratext *) DOCUMENT, (oratext *) 0, flags))
return 1;

    cout << "\nThe elements are:\n";
    dump(parser.getDocumentElement());
    (void) parser.xmlterm();	// terminate LPX package
    return 0;
}

//
// dump
//

void dump(Node *node)
{
    uword i, n_nodes;
    NodeList *nodes;
    size_t   nn;
    
    String qName;
    String localName;
    String nsName;
    String prefix;

    if (node == NULL)
       return;
    if (nodes = node->getChildNodes())
    {      
       for (nn = node->numChildNodes(), i=0; i < nn; i++)
       {
          // Use the methods getQualifiedName(), getLocalName(), 
          // getPrefix(), and getNamespace() to get Namespace
          // information.

          qName = prefix = localName = nsName = (oratext *)" ";

  if (node->getQualifiedName() != (oratext *)NULL)
              qName = node->getQualifiedName();

  if (node->getPrefix() != (oratext *)NULL)
              prefix = node->getPrefix();

  if (node->getLocal() != (oratext *)NULL)
              localName = node->getLocal();

  if (node->getNamespace() != (oratext *)NULL)
              nsName = node->getNamespace();
          cout << "  ELEMENT Qualified Name: " << (char *)qName << "\n";   
          cout << "  ELEMENT Prefix        : " << (char *)prefix << "\n";
          cout << "  ELEMENT Local Name    : " << (char *)localName << "\n";
          cout << "  ELEMENT Namespace     : " << (char *)nsName << "\n";
          dumpattrs(node);
          dump(node->getChildNode(i));
       }
    }
}

//
// dumpattrs
//

void dumpattrs(Node *node)
{
    NamedNodeMap  *attrs;
    Attr          *a;
    uword          i;
    size_t         na;

    oratext   *qname;
    oratext   *namespce;
    oratext   *local;
    oratext   *prefix;
    oratext   *value;
    if (attrs = node->getAttributes())
    {
       cout << "\n    ATTRIBUTES: \n";
       for (na = attrs->getLength(), i = 0; i < na; i++)
       { 
          /* get attr qualified name, local name, namespace, and prefix */

          a = (Attr *)attrs->item(i);
          qname = namespce = local = prefix = value = (oratext*)" ";
          if (a->getQualifiedName() != (oratext*)NULL)
             qname = a->getQualifiedName();
          if (a->getNamespace() != (oratext*)NULL)
             namespce = a->getNamespace();
          if (a->getLocal() != (oratext*)NULL)
             local = a->getLocal();
          if (a->getPrefix() != (oratext*)NULL)
             prefix = a->getPrefix();
          if (a->getValue() != (oratext*)NULL)
             value = a->getValue();

          cout << "      " << (char*)qname << " = " << (char*)value << "\n";
          cout << "      Namespace : " << (char*)namespce << "\n";
          cout << "      Local Name: " << (char*)local << "\n";
          cout << "      Prefix    : " << (char*)prefix << "\n\n";
       }
    }
    cout << "\n";
}

XML Parser for C++ Example 11: C++ -- DOMNamespace.std

DOMNamespace.std shows the expected output from DOMNamespace.cpp.

XML C++ DOM Namespace
Initializing XML package...
Parsing 'NSExample.xml'...

The elements are:
  ELEMENT Qualified Name: doc
  ELEMENT Prefix        :  
  ELEMENT Local Name    : doc
  ELEMENT Namespace     : http://www.w3c.org

    ATTRIBUTES: 
      nsprefix:a1 = v1
      Namespace : http://www.oracle.com
      Local Name: a1
      Prefix    : nsprefix

      xmlns = http://www.w3c.org
      Namespace :  
      Local Name: xmlns
      Prefix    :  

      xmlns:nsprefix = http://www.oracle.com
      Namespace :  
      Local Name: nsprefix
      Prefix    : xmlns

  ELEMENT Qualified Name: child
  ELEMENT Prefix        :  
  ELEMENT Local Name    : child
  ELEMENT Namespace     : http://www.w3c.org

XML Parser for C++ Example 12: C++ -- SAXNamespace.cpp

This example contains the C++ source code for the SAXNamespace program.

// Copyright (c) Oracle Corporation 1999, 2000. All Rights Reserved.

//////////////////////////////////////////////////////////////////////////////
// NAME
//   DOMNamespace.cpp
//
// DESCRIPTION
//   This file demonstates a simple use of the parser and Namespace
//   extensions to the SAX APIs. 
//   The XML file that is given to the application is parsed and the
//   elements and attributes in the document are printed.
//
// PUBLIC FUNCTION(S)
//
// PRIVATE FUNCTION(S)
//
// NOTES
//   none
//////////////////////////////////////////////////////////////////////////////

#include <iostream.h>

#ifndef ORAXMLDOM_ORACLE
# include <oraxmldom.h>
#endif

#define DOCUMENT         "NSExample.xml"

/*------------------------------------------------------------------------
                           FUNCTION PROTOTYPES
  ------------------------------------------------------------------------*/
int startDocument(void *ctx);
int endDocument(void *ctx);
int endElement(void *ctx, const oratext *name);
int nsStartElement(void *ctx, const oratext *qname, 
                        const oratext *local, 
                        const oratext *nsp,
                        const struct xmlnodes *attrs);

/* SAX callback structure */

xmlsaxcb saxcb = {
    startDocument,
    endDocument,
    0,
    endElement,
    0,
    0,
    0,
    0,
    0,
    nsStartElement,
    0, 0, 0, 0, 0, 0, 0, 0
};

/* SAX callback context */
/*
typedef struct {
    xmlctx  *ctx;
    uword    depth;
} cbctx;
*/

/*------------------------------------------------------------------------
                                MAIN
  ------------------------------------------------------------------------*/
int main()
{
   XMLParser   parser;
   ub4         flags;
   uword       ecode;
   flags = XML_FLAG_VALIDATE | XML_FLAG_DISCARD_WHITESPACE;
   cout << "XML C++ SAX Namespace\n";
   cout << "Initializing XML package...\n";
   if (ecode = parser.xmlinit((oratext *) 0,           // encoding
                                 (void (*)(void *, const oratext *, ub4)) 0,
                                 (void *) 0,           // msghdlr ctx
                                 (xmlsaxcb *) &saxcb)) // SAX callback
   {
       cout << "Failed to initialize XML parser, error " << ecode;
       return 1;
   }

   /* parse the document */

   cout << "Parsing '" << DOCUMENT << "'...\n";
   cout.flush();
   if (ecode = parser.xmlparse((oratext *) DOCUMENT, (oratext *) 0, flags))
      return 1;

   (void) parser.xmlterm();	// terminate LPX package

   return 0;
}

/*------------------------------------------------------------------------
                             SAX Interface
  ------------------------------------------------------------------------*/
int startDocument(void *ctx)
{
    cout << "\nStartDocument\n\n";
    return 0;
}

int endDocument(void *ctx)
{
    cout << "\nEndDocument\n";
    return 0;
}

int endElement(void *ctx, const oratext *name)
{
    cout << "\nELEMENT Name  : " << (char*)name << "\n";
    return 0;
}

int nsStartElement(void *ctx, const oratext *qname, const oratext *local, 
                   const oratext *nsp, const struct xmlnodes *attrs)
{
    xmlnode *attr;
    uword    i;
    oratext *aqname;
    oratext *alocal;
    oratext *anamespace;
    oratext *aprefix;
    oratext *avalue;

    /*
     * Use the functions getXXXQualifiedName(), getXXXLocalName(), and
     * getXXXNamespace() to get Namespace information.
     */

    if (qname == (oratext*)NULL)
       qname = (oratext*)" ";
    if (local == (oratext*)NULL)
       local = (oratext*)" ";
    if (nsp == (oratext*)NULL)
       nsp = (oratext*)" ";
    
    cout << "ELEMENT Qualified Name: " << (char*)qname << "\n";
    cout << "ELEMENT Local Name    : " << (char*)local << "\n";
    cout << "ELEMENT Namespace     : " << (char*)nsp << "\n";

    if (attrs)
    {
       for (i = 0; i < numAttributes(attrs); i++)
       {
          attr = getAttributeIndex(attrs,i);
          aqname = alocal = anamespace = aprefix = avalue = (oratext*)" ";

          if (getAttrQualifiedName(attr))
             aqname = (oratext *) getAttrQualifiedName(attr);
          if (getAttrPrefix(attr))
             aprefix = (oratext *) getAttrPrefix(attr);
          if (getAttrLocal(attr))
             alocal = (oratext *) getAttrLocal(attr);
          if (getAttrNamespace(attr))
             anamespace = (oratext *) getAttrNamespace(attr);
          if (getAttrValue(attr))
             avalue = (oratext *) getAttrValue(attr);

         cout << " ATTRIBUTE Qualified Name   : " << (char*)aqname << "\n";
         cout << " ATTRIBUTE Prefix           : " << (char*)aprefix << "\n";
         cout << " ATTRIBUTE Local Name       : " << (char*)alocal << "\n";
         cout << " ATTRIBUTE Namespace        : " << (char*)anamespace << "\n";
         cout << " ATTRIBUTE Value            : " << (char*)avalue << "\n";
         cout << "\n";
       }
    }
    return 0;
}

XML Parser for C++ Example 13: C++ -- SAXNamespace.std

SAXNamespace.std shows the expected output from SAXNamespace.cpp.

XML C++ SAX Namespace
Initializing XML package...
Parsing 'NSExample.xml'...

StartDocument

ELEMENT Qualified Name: doc
ELEMENT Local Name    : doc
ELEMENT Namespace     : http://www.w3c.org
 ATTRIBUTE Qualified Name   : nsprefix:a1
 ATTRIBUTE Prefix           : nsprefix
 ATTRIBUTE Local Name       : a1
 ATTRIBUTE Namespace        : http://www.oracle.com
 ATTRIBUTE Value            : v1

 ATTRIBUTE Qualified Name   : xmlns
 ATTRIBUTE Prefix           :  
 ATTRIBUTE Local Name       : xmlns
 ATTRIBUTE Namespace        :  
 ATTRIBUTE Value            : http://www.w3c.org

 ATTRIBUTE Qualified Name   : xmlns:nsprefix
 ATTRIBUTE Prefix           : xmlns
 ATTRIBUTE Local Name       : nsprefix
 ATTRIBUTE Namespace        :  
 ATTRIBUTE Value            : http://www.oracle.com

ELEMENT Qualified Name: child
ELEMENT Local Name    : child
ELEMENT Namespace     : http://www.w3c.org

ELEMENT Name  : child
ELEMENT Name  : doc
EndDocument

XML Parser for C++ Example 14: C++ -- FullDOM.cpp

This example contains the C++ source code for FullDOM.cpp.

// Copyright (c) Oracle Corporation 1999, 2000. All Rights Reserved.

//////////////////////////////////////////////////////////////////////////////
// NAME
//   FullDOM.cpp
//
// DESCRIPTION
//   Sample code to test full C++ DOM interface
//////////////////////////////////////////////////////////////////////////////

#include <iostream.h>

#ifndef ORAXMLDOM_ORACLE
# include <oraxmldom.h>
#endif

#define TEST_DOC	(oratext *) "FullDOM.xml"

void dump(Node *node, uword level);
void dumpnode(Node *node, uword level);

static char *ntypename[] = {
    "0",
    "ELEMENT",
    "ATTRIBUTE",
    "TEXT",
    "CDATA",
    "ENTREF",
    "ENTITY",
    "PI",
    "COMMENT",
    "DOCUMENT",
    "DTD",
    "DOCFRAG",
    "NOTATION"
};

#define FAIL { cout << "Failed!\n"; return 1; }

int main()
{
    XMLParser     parser;
    Document     *doc;
    Element      *root, *elem, *subelem;
    Attr         *attr, *attr1, *attr2, *gleep1, *gleep2;
    Text         *text, *subtext;
    Node         *node, *pi, *comment, *entref, *cdata, *clone,
 *deep_clone, *frag, *fragelem, *fragtext, *sub2,
 *fish, *food, *food2, *repl;
    NodeList     *subs, *nodes;
    NamedNodeMap *attrs, *notes, *entities;
    DocumentType *dtd;
    uword         i, ecode, level;

    cout << "XML C++ Full DOM test\n";
    cout << "Initializing XML parser...\n";

    if (ecode = parser.xmlinit())
    {
cout << "Failed to initialze XML parser, error " << ecode << "\n";
return 1;
    }

    cout << "\nCreating new document...\n";
    if (!(doc = parser.createDocument()))
FAIL

    cout << "Document from root node:\n";
    dump(parser.getDocument(), 0);

    cout << "\nCreating root element ('ROOT')...\n";
    if (!(elem = doc->createElement((oratext *) "ROOT")))
FAIL

    cout << "Setting as root element...\n";
    if (!doc->appendChild(elem))
FAIL

    cout << "Document from 'ROOT' element:\n";
    dump(root = parser.getDocumentElement(), 0);
    cout << "Adding 7 children to 'ROOT' element...\n";
    if (!(text = doc->createTextNode((oratext *) "Gibberish")) ||
        !elem->appendChild(text))
FAIL
    if (!(comment = doc->createComment((oratext*) "Bit warm today, innit?")) ||
        !elem->appendChild(comment))
FAIL

    if (!(pi = doc->createProcessingInstruction((oratext *) "target",
(oratext *) "PI-contents")) ||
       !elem->appendChild(pi))
FAIL

    if (!(cdata = doc->createCDATASection((oratext *) "See DATA")) ||
        !elem->appendChild(cdata))
FAIL

    if (!(entref = doc->createEntityReference((oratext *) "EntRef")) ||
        !elem->appendChild(entref))
FAIL

    if (!(fish = doc->createElement((oratext *) "FISH")) ||
!elem->appendChild(fish))
FAIL

    if (!(food = doc->createElement((oratext *) "FOOD")) ||
!elem->appendChild(food))
FAIL
    cout << "Document from 'ROOT' element with its 7 children:\n";
    dump(root, 0);

    cout << "\nTesting node insertion...\n";
    cout << "Adding 'Pre-Gibberish' text node and 'Ask about the weather' 
comment node...\n";
    if (!(node = doc->createTextNode((oratext *) "Pre-Gibberish")) ||
        !elem->insertBefore(node, text))
FAIL

    if (!(node = doc->createComment((oratext *) "Ask about the weather:")) ||
        !elem->insertBefore(node, comment))
FAIL

    cout << "Document from 'ROOT' element:\n";
    dump(root, 0);
    cout << "Document from 'ROOT' element:\n";
    dump(root, 0);
    cout << "Document from 'ROOT' element:\n";
    dump(root, 0);
    cout << "\nTesting nextSibling links starting at first child...\n";
    for (node = elem->getFirstChild();
    node;
    node = node->getNextSibling())dump(node, 1);
    cout << "\nTesting previousSibling links starting at last child...\n";
    for (node = elem->getLastChild();
    node;
    node = node->getPreviousSibling())dump(node, 1);

    cout << "\nTesting setting node value...\n";
    cout << "Original node:\n";
    dump(pi, 1);
    pi->setValue((oratext *) "New PI contents");
    cout << "Node after new value:\n";
    dump(pi, 1);

    cout << "\nAdding another element level, i.e., 'SUB'...\n";
    if (!(subelem = doc->createElement((oratext *) "SUB")) ||
!elem->insertBefore(subelem, cdata) ||
!(subtext = doc->createTextNode((oratext *) "Lengthy SubText")) ||
        !subelem->appendChild(subtext))
FAIL

    cout << "Document from 'ROOT' element:\n";
    dump(root, 0);

    cout << "\nAdding a second 'SUB' element...\n";
    if (!(sub2 = doc->createElement((oratext *) "SUB")) ||
!elem->insertBefore(sub2, cdata))
FAIL

    cout << "Document from 'ROOT' element:\n";
    dump(root, 0);

    cout << "\nGetting all SUB nodes - note the distinct hex addresses...\n";
    if (!(subs = doc->getElementsByTagName(root, (oratext *) "SUB")))
FAIL
    for (i = 0; i < subs->getLength(); i++)
dumpnode(subs->item(i), 1);

    cout << "\nTesting parent links...\n";
    for (level = 1, node = subtext; node; node = node->getParentNode(), level++)
dumpnode(node, level);

    cout << "\nTesting owner document of node...\n";
    dumpnode(subtext, 1);
    dumpnode(subtext->getOwnerDocument(), 1);

    cout << "\nTesting node replacement...\n";
    if (!(node = doc->createTextNode((oratext *) "REPLACEMENT, 1/2 PRICE")) ||
        !pi->replaceChild(node))
FAIL

    cout << "Document from 'ROOT' element:\n";
    dump(root, 0);

    cout << "\nTesting node removal...\n";
    if (!entref->removeChild())
FAIL

    cout << "Document from 'ROOT' element:\n";
    dump(root, 0);
    cout << "\nNormalizing...\n";
    elem->normalize();
    cout << "Document from 'ROOT' element:\n";
    dump(root, 0);
    cout << "\nCreating and populating document fragment...\n";
    if (!(frag = doc->createDocumentFragment()) ||
!(fragelem = doc->createElement((oratext *) "FragElem")) ||
!(fragtext = doc->createTextNode((oratext *) "FragText")) ||
!frag->appendChild(fragelem) ||
!frag->appendChild(fragtext))
FAIL
    dump(frag, 1);
    cout << "Insert document fragment...\n";
    if (!elem->insertBefore(frag, comment))
FAIL
    dump(elem, 1);

    cout << "\nCreate two attributes...\n";
    if (!(attr1 = doc->createAttribute((oratext*)"Attr1",(oratext*)"Value1")) ||
!(attr2 = doc->createAttribute((oratext*)"Attr2",(oratext*)"Value2")))
FAIL
    cout << "Setting attributes...\n";
    if (!subelem->setAttributeNode(attr1, NULL) ||
!subelem->setAttributeNode(attr2, NULL))
FAIL
    dump(subelem, 1);

    cout << "\nAltering attribute1 value...\n";
    attr1->setValue((oratext *) "New1");
    dump(subelem, 1);

    cout << "\nFetching attribute by name (Attr2)...\n";
    if (!(node = subelem->getAttributeNode((oratext *) "Attr2")))
FAIL
    dump(node, 1);

    cout << "\nRemoving attribute by name (Attr1)...\n";
    subelem->removeAttribute((oratext *) "Attr1");
    dump(subelem, 1);

    cout << "\nAdding new attribute...\n";
    if (!subelem->setAttribute((oratext *) "Attr3", (oratext *) "Value3"))
FAIL
    dump(subelem, 1);

    cout << "\nRemoving attribute by pointer (Attr2)...\n";
    if (!subelem->removeAttributeNode(attr2))
FAIL
    dump(subelem, 1);

    cout << "\nAdding new attribute w/same name (test replacement)...\n";
    dump(subelem, 1);
    if (!(attr = doc->createAttribute((oratext*)"Attr3", (oratext*)"Zoo3")))
FAIL
    if (!subelem->setAttributeNode(attr, NULL))
FAIL
    dump(subelem, 1);

    cout << "\nTesting node (attr) set by name...\n";
    cout << "Adding 'GLEEP' attr and printing out hex addresses of node set\n";
    attrs = subelem->getAttributes();
    if (!(gleep1=doc->createAttribute((oratext*)"GLEEP",(oratext*)"GLEEP1")) ||
!attrs->setNamedItem(gleep1, NULL))
FAIL
    dump(subelem, 0);

    cout << "\nTesting node (attr) set by name...\n";
    cout << "Replacing 'GLEEP' element - note the changed hex address\n";
    if (!(gleep2=doc->createAttribute((oratext*)"GLEEP",(oratext*)"GLEEP2")) ||
!attrs->setNamedItem(gleep2, &repl))
FAIL
    dump(subelem, 0);
    cout << "Replaced node was:\n";
    dump(repl, 1);

    cout << "\nTesting node removal by name...\n";
    cout << "Removing 'GLEEP' attribute\n";
    if (!attrs->removeNamedItem((oratext *) "GLEEP"))
FAIL
    dump(subelem, 0);

    cout << "\nOriginal SubROOT...\n";
    dump(subelem, 1);
    cout << "Cloned SubROOT (not deep)...\n";
    clone = subelem->cloneNode(FALSE);
    dump(clone, 1);
    cout << "Cloned SubROOT (deep)...\n";
    deep_clone = subelem->cloneNode(TRUE);
    dump(deep_clone, 1);

    cout << "\nSplitting text...\n";
    dump(subelem, 1);
    subtext->splitText(3);
    dump(subelem, 1);

    cout << "\nTesting string operations...\n";
    cout << "    CharData = \"" << (char *) subtext->getData() << "\"\n";
    cout << "Setting new data...\n";
    subtext->setData((oratext *) "0123456789");
    cout << "    CharData = \"" << (char *) subtext->getData() << "\"\n";
    cout << "    CharLength = " << (int) subtext->getLength() << "\n";
    cout << "    Substring(0,5) = \"" <<
(char *) subtext->substringData(0, 5) << "\"\n";
    cout << "    Substring(8,2) = \"" <<
(char *) subtext->substringData(8, 2) << "\"\n";
    cout << "Appending data...\n";
    subtext->appendData((oratext *) "ABCDEF");
    cout << "    CharData = \"" << (char *) subtext->getData() << "\"\n";
    cout << "Inserting data...\n";
    subtext->insertData(10, (oratext *) "*foo*");
    cout << "    CharData = \"" << (char *) subtext->getData() << "\"\n";
    cout << "Deleting data...\n";
    subtext->deleteData(0, 10);
    cout << "    CharData = \"" << (char *) subtext->getData() << "\"\n";
    cout << "Replacing data...\n";
    subtext->replaceData(1, 3, (oratext *) "bamboozle");
    cout << "    CharData = \"" << (char *) subtext->getData() << "\"\n";

    cout << "Cleaning up...\n";
    parser.xmlclean();

    if (parser.getDocument())
    {
cout << "Problem, document is not gone!!\n";
return 1;
    }

    cout << "Parsing test document...\n";
    if (ecode = parser.xmlparse(TEST_DOC, (oratext *) 0, 0))
    {
cout << "Parse failed, code " << ecode << "\n";;
return ecode;
    }

    cout << "Document from root node:\n" << flush;
    dump(parser.getDocument(), 0);

    cout << "Testing getNotations...\n" << flush;
    dtd = parser.getDocType();
    if (notes = dtd->getNotations())
    {
cout << "# of notations = " << notes->getLength() << "\n" << flush;
for (i = 0; i < notes->getLength(); i++)
    dump(notes->item(i), 1);
    }
    else
cout << "No defined notations\n" << flush;

    cout << "Testing getEntities...\n" << flush;
    if (entities = dtd->getEntities())
    {
cout << "# of entities = " << entities->getLength() << "\n" << flush;
for (i = 0; i < entities->getLength(); i++)
    dump(entities->item(i), 1);
    }
    else
cout << "No defined entities\n" << flush;

    cout << "Cleaning up...\n";
    parser.xmlclean();

    if (parser.getDocument())
    {
cout << "Problem, document is not gone!!\n";
return 1;
    }

    cout << "\nTerminating parser...\n";
    parser.xmlterm();

    cout << "Success.\n";
    return 0;
}

void dump(Node *node, uword level)
{
    NodeList *nodes;
    uword     i, n_nodes;

    if (node)
    {
dumpnode(node, level);
if (node->hasChildNodes())
{
    nodes = node->getChildNodes();
    n_nodes = node->numChildNodes();
    for (i = 0; i < n_nodes; i++)
dump(nodes->item(i), level + 1);
}
    }
}

void dumpnode(Node *node, uword level)
{
    const oratext *name, *value;
    short          type;
    NamedNodeMap  *attrs;
    Attr          *attr;
    uword          i, n_attrs;

    if (node)
    {
for (i = 0; i <= level; i++)
    cout << "    ";
type = node->getType();
cout << (char *) ntypename[type];
if ((name = node->getName()) && (*name != '#'))
    cout << " \"" << (char *) name << "\"";
if (value = node->getValue())
    cout << " = \"" << (char *) value << "\"";
if ((type == ELEMENT_NODE) && (attrs = node->getAttributes()))
{
    cout << " [";
    n_attrs = attrs->getLength();
    for (i = 0; i < n_attrs; i++)
    {
if (i) cout << ", ";
attr = (Attr *) attrs->item(i);
cout << (char *) attr->getName();
if (attr->getSpecified())
    cout << "*";
cout << "=\"" << (char *) attr->getValue() << "\"";
    }
    cout << "]";
}
cout << "\n";
    }
}

// end of FullDOM.cpp

XML Parser for C++ Example 15: C++ -- FullDOM.std

The FullDOM.std example file shows the expected output from FullDOM.cpp

XML C++ Full DOM test
Initializing XML parser...

Creating new document...
Document from root node:
    DOCUMENT

Creating root element ('ROOT')...
Setting as root element...
Document from 'ROOT' element:
    ELEMENT "ROOT"
Adding 7 children to 'ROOT' element...
Document from 'ROOT' element with its 7 children:
    ELEMENT "ROOT"
        TEXT = "Gibberish"
        COMMENT = "Bit warm today, innit?"
        PI "target" = "PI-contents"
        CDATA = "See DATA"
        ENTREF "EntRef"
        ELEMENT "FISH"
        ELEMENT "FOOD"

Testing node insertion...
Adding 'Pre-Gibberish' text node and 'Ask about the weather' comment node...
Document from 'ROOT' element:
    ELEMENT "ROOT"
        TEXT = "Pre-Gibberish"
        TEXT = "Gibberish"
        COMMENT = "Ask about the weather:"
        COMMENT = "Bit warm today, innit?"
        PI "target" = "PI-contents"
        CDATA = "See DATA"
        ENTREF "EntRef"
        ELEMENT "FISH"
        ELEMENT "FOOD"
Document from 'ROOT' element:
    ELEMENT "ROOT"
        TEXT = "Pre-Gibberish"
        TEXT = "Gibberish"
        COMMENT = "Ask about the weather:"
        COMMENT = "Bit warm today, innit?"
        PI "target" = "PI-contents"
        CDATA = "See DATA"
        ENTREF "EntRef"
        ELEMENT "FISH"
        ELEMENT "FOOD"
Document from 'ROOT' element:
    ELEMENT "ROOT"
        TEXT = "Pre-Gibberish"
        TEXT = "Gibberish"
        COMMENT = "Ask about the weather:"
        COMMENT = "Bit warm today, innit?"
        PI "target" = "PI-contents"
        CDATA = "See DATA"
        ENTREF "EntRef"
        ELEMENT "FISH"
        ELEMENT "FOOD"

Testing nextSibling links starting at first child...
        TEXT = "Pre-Gibberish"
        TEXT = "Gibberish"
        COMMENT = "Ask about the weather:"
        COMMENT = "Bit warm today, innit?"
        PI "target" = "PI-contents"
        CDATA = "See DATA"
        ENTREF "EntRef"
        ELEMENT "FISH"
        ELEMENT "FOOD"

Testing previousSibling links starting at last child...
        ELEMENT "FOOD"
        ELEMENT "FISH"
        ENTREF "EntRef"
        CDATA = "See DATA"
        PI "target" = "PI-contents"
        COMMENT = "Bit warm today, innit?"
        COMMENT = "Ask about the weather:"
        TEXT = "Gibberish"
        TEXT = "Pre-Gibberish"

Testing setting node value...
Original node:
        PI "target" = "PI-contents"
Node after new value:
        PI "target" = "New PI contents"

Adding another element level, i.e., 'SUB'...
Document from 'ROOT' element:
    ELEMENT "ROOT"
        TEXT = "Pre-Gibberish"
        TEXT = "Gibberish"
        COMMENT = "Ask about the weather:"
        COMMENT = "Bit warm today, innit?"
        PI "target" = "New PI contents"
        ELEMENT "SUB"
            TEXT = "Lengthy SubText"
        CDATA = "See DATA"
        ENTREF "EntRef"
        ELEMENT "FISH"
        ELEMENT "FOOD"

Adding a second 'SUB' element...
Document from 'ROOT' element:
    ELEMENT "ROOT"
        TEXT = "Pre-Gibberish"
        TEXT = "Gibberish"
        COMMENT = "Ask about the weather:"
        COMMENT = "Bit warm today, innit?"
        PI "target" = "New PI contents"
        ELEMENT "SUB"
            TEXT = "Lengthy SubText"
        ELEMENT "SUB"
        CDATA = "See DATA"
        ENTREF "EntRef"
        ELEMENT "FISH"
        ELEMENT "FOOD"

Getting all SUB nodes - note the distinct hex addresses...
        ELEMENT "SUB"
        ELEMENT "SUB"

Testing parent links...
        TEXT = "Lengthy SubText"
            ELEMENT "SUB"
                ELEMENT "ROOT"
                    DOCUMENT

Testing owner document of node...
        TEXT = "Lengthy SubText"
        DOCUMENT

Testing node replacement...
Document from 'ROOT' element:
    ELEMENT "ROOT"
        TEXT = "Pre-Gibberish"
        TEXT = "Gibberish"
        COMMENT = "Ask about the weather:"
        COMMENT = "Bit warm today, innit?"
        TEXT = "REPLACEMENT, 1/2 PRICE"
        ELEMENT "SUB"
            TEXT = "Lengthy SubText"
        ELEMENT "SUB"
        CDATA = "See DATA"
        ENTREF "EntRef"
        ELEMENT "FISH"
        ELEMENT "FOOD"

Testing node removal...
Document from 'ROOT' element:
    ELEMENT "ROOT"
        TEXT = "Pre-Gibberish"
        TEXT = "Gibberish"
        COMMENT = "Ask about the weather:"
        COMMENT = "Bit warm today, innit?"
        TEXT = "REPLACEMENT, 1/2 PRICE"
        ELEMENT "SUB"
            TEXT = "Lengthy SubText"
        ELEMENT "SUB"
        CDATA = "See DATA"
        ELEMENT "FISH"
        ELEMENT "FOOD"

Normalizing...
Document from 'ROOT' element:
    ELEMENT "ROOT"
        TEXT = "Pre-GibberishGibberish"
        COMMENT = "Ask about the weather:"
        COMMENT = "Bit warm today, innit?"
        TEXT = "REPLACEMENT, 1/2 PRICE"
        ELEMENT "SUB"
            TEXT = "Lengthy SubText"
        ELEMENT "SUB"
        CDATA = "See DATA"
        ELEMENT "FISH"
        ELEMENT "FOOD"

Creating and populating document fragment...
        DOCFRAG
            ELEMENT "FragElem"
            TEXT = "FragText"
Insert document fragment...
        ELEMENT "ROOT"
            TEXT = "Pre-GibberishGibberish"
            COMMENT = "Ask about the weather:"
            ELEMENT "FragElem"
            TEXT = "FragText"
            COMMENT = "Bit warm today, innit?"
            TEXT = "REPLACEMENT, 1/2 PRICE"
            ELEMENT "SUB"
                TEXT = "Lengthy SubText"
            ELEMENT "SUB"
            CDATA = "See DATA"
            ELEMENT "FISH"
            ELEMENT "FOOD"

Create two attributes...
Setting attributes...
        ELEMENT "SUB" [Attr1*="Value1", Attr2*="Value2"]
            TEXT = "Lengthy SubText"

Altering attribute1 value...
        ELEMENT "SUB" [Attr1*="New1", Attr2*="Value2"]
            TEXT = "Lengthy SubText"

Fetching attribute by name (Attr2)...
        ATTRIBUTE "Attr2" = "Value2"

Removing attribute by name (Attr1)...
        ELEMENT "SUB" [Attr2*="Value2"]
            TEXT = "Lengthy SubText"

Adding new attribute...
        ELEMENT "SUB" [Attr2*="Value2", Attr3*="Value3"]
            TEXT = "Lengthy SubText"

Removing attribute by pointer (Attr2)...
        ELEMENT "SUB" [Attr3*="Value3"]
            TEXT = "Lengthy SubText"

Adding new attribute w/same name (test replacement)...
        ELEMENT "SUB" [Attr3*="Value3"]
            TEXT = "Lengthy SubText"
        ELEMENT "SUB" [Attr3*="Zoo3"]
            TEXT = "Lengthy SubText"

Testing node (attr) set by name...
Adding 'GLEEP' attr and printing out hex addresses of node set
    ELEMENT "SUB" [Attr3*="Zoo3", GLEEP*="GLEEP1"]
        TEXT = "Lengthy SubText"

Testing node (attr) set by name...
Replacing 'GLEEP' element - note the changed hex address
    ELEMENT "SUB" [Attr3*="Zoo3", GLEEP*="GLEEP2"]
        TEXT = "Lengthy SubText"
Replaced node was:
        ATTRIBUTE "GLEEP" = "GLEEP1"

Testing node removal by name...
Removing 'GLEEP' attribute
    ELEMENT "SUB" [Attr3*="Zoo3"]
        TEXT = "Lengthy SubText"

Original SubROOT...
        ELEMENT "SUB" [Attr3*="Zoo3"]
            TEXT = "Lengthy SubText"
Cloned SubROOT (not deep)...
        ELEMENT "SUB" [Attr3*="Zoo3"]
            TEXT = "Lengthy SubText"
Cloned SubROOT (deep)...
        ELEMENT "SUB" [Attr3*="Zoo3"]
            TEXT = "Lengthy SubText"

Splitting text...
        ELEMENT "SUB" [Attr3*="Zoo3"]
            TEXT = "Lengthy SubText"
        ELEMENT "SUB" [Attr3*="Zoo3"]
            TEXT = "Leng"
            TEXT = "thy SubText"

Testing string operations...
    CharData = "Leng"
Setting new data...
    CharData = "0123456789"
    CharLength = 10
    Substring(0,5) = "01234"
    Substring(8,2) = "89"
Appending data...
    CharData = "0123456789ABCDEF"
Inserting data...
    CharData = "0123456789*foo*ABCDEF"
Deleting data...
    CharData = "*foo*ABCDEF"
Replacing data...
    CharData = "*bamboozle*ABCDEF"
Cleaning up...
Parsing test document...
Document from root node:
    DOCUMENT
        DTD "doc"
        ELEMENT "doc" [xml:lang*="foo"]
            ELEMENT "p" [xml:space="preserve"]
                TEXT = "An ampersand (&) may be escaped
numerically (&#38;) or with a general entity
(&amp;)."
Testing getNotations...
# of notations = 2
        NOTATION "notation1"
        NOTATION "notation2"
Testing getEntities...
# of entities = 1
        ENTITY "example" = "<p>An ampersand (&#38;) may be escaped
numerically (&#38;#38;) or with a general entity
(&amp;amp;).</p>"
Cleaning up...

Terminating parser...
Success.

XML Parser for C++ Example 16: C++ -- XSLSample.cpp

This example contains the C++ source code for XSLSample.cpp

// Copyright (c) Oracle Corporation 1999. All Rights Reserved.

///////////////////////////////////////////////////////////////////////////////
// NAME
//   XSLSample.cpp
//
// DESCRIPTION
//   Sample usage of C++ XSL processor
//
// PUBLIC FUNCTION(S)
//
// PRIVATE FUNCTION(S)
//
// NOTES
//   none
///////////////////////////////////////////////////////////////////////////////

#ifndef ORAXMLDOM_ORACLE
# include <oraxmldom.h>
#endif

int main(int argc, char **argv)
{
    XMLParser     xmlpar, xslpar, respar;
    XSLProcessor  xslproc;
    Node         *result;
    ub4           flags;
    uword         ecode;
    flags = XML_FLAG_VALIDATE | XML_FLAG_DISCARD_WHITESPACE;

    cout << "XSL processor sample\n";

    if (argc < 3)
    {
	cout << "Usage is XSLSample <xmlfile> <stlyesheet>\n";
	return 1;
    }
 
    // Parse the XML file
    cout << "Parsing XML file " << argv[1] << "\n";
    if (ecode = xmlpar.xmlinit())
    {
        cout << "Failed to initialize XML parser, error " << ecode << "\n";;
        return 1;
    }
    if (ecode = xmlpar.xmlparse((oratext *) argv[1], (oratext *) 0, flags))
        return 1;

    // Parse the Stylesheet file
    cout << "Parsing Stylesheet " << argv[2] << "\n";
    if (ecode = xslpar.xmlinit())
    {
        cout << "Failed to initialize XML parser, error " << ecode << "\n";;
        return 1;
    }
    if (ecode = xslpar.xmlparse((oratext *) argv[2], (oratext *) 0, flags))
        return 1;

    // Initialize the result context
    cout << "Initializing the result context\n";
    if (ecode = respar.xmlinit())
    {
        cout << "Failed to initialize XML parser, error " << ecode << "\n";;
        return 1;
    }
    
    // XSL Processing
    cout << "XSL Processing\n";
    if (ecode = xslproc.xslprocess(&xmlpar, &xslpar, &respar, &result))
    {
        cout << "Failed in XSL Processing, error " << ecode << "\n";;
        return 1;
    }  

    // print the resultant tree
    cout.flush();
    xslproc.printres(&respar, result);


    // Terminate the parsers
    (void) xmlpar.xmlterm();    
    (void) xslpar.xmlterm();    
    (void) respar.xmlterm();    

    return 0;
}

XML Parser for C++ Example 17: C++ -- XSLSample.std

This example shows the typical result output from XSLSample.cpp

<xsl:param name="size"/>
<xsl:param name="data"/>	
<xsl:choose>		<xsl:when test="number(number($size) < 
string-length(string($data)))">		
   <xsl:value-of select="substring(string($data), 1, number($size))"/>		
</xsl:when>		
<xsl:otherwise>			
<xsl:value-of select="string($data)"/>
</xsl:otherwise>	</xsl:choose>	
<xsl:if test="number(number($size) > string-length(string($data)))">		
<xsl:call-template name="pad">			
<xsl:with-param name="padsize" select="number($size) - 
string-length(string($data))"/>		
</xsl:call-template>	</xsl:if></xsl:template><xsl:template match="/">   
<xsl:text>&#13;&#10;</xsl:text>	<xsl:apply-templates select="//ROWSE
T/ROW/CUSTOMER"/>
   <xsl:text>&#13;&#10;</xsl:text>
</xsl:template><xsl:template match="CUSTOMER">
<xsl:call-template name="truncateorpad">
<xsl:with-param name="size" select="31"/>		
<xsl:with-param name="data" select ="."/>	
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>


Go to previous page Go to next page
Oracle
Copyright © 1996-2001, Oracle Corporation.

All Rights Reserved.
Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index