PrevNextUpHome SophiaFramework UNIVERSE 5.3

19.7. Sample Code

19.7.1. XMLDOM Parser

Example 19.2. XML document to be parsed (file.xml)

<fruit>
  <name>apple</name>
  <size>XS</size>
  <color>red</color>
</fruit>

Example 19.3. Get the elements

SFXXMLDOMParser parser;     // DOM Parser
SFCError error;             // error value
SFXAnsiString resultString; // variable to store node name

// parse XML document in file.xml
if ((error = parser.Parse(SFXPath("/file.xml"))) == SFERR_NO_ERROR) {

    // get root node of DOM tree
    SFXXMLDocumentPtr root = parser.GetDocument(); 

    // get first child of root node
    SFXXMLNodePtr child = root->GetFirstChild();   

    // get node name (resultString will be "fruit")
    resultString = child->GetNodeName();

    // get node type (node type will be ELEMENT_NODE)
    SFXXMLNode::NodeType type = child->GetNodeType();

    // get first child node of this node
    SFXXMLNodePtr node = child->GetFirstChild();   

    // get node name (resultString will be "name")
    resultString = node->GetNodeName();

    // get node type (node type will be ELEMENT_NODE)
    type = node->GetNodeType();

    // get first child node of this node
    SFXXMLNodePtr textNode = node->GetFirstChild(); 

    // get node name (resultString will be "apple")
    resultString = textNode->GetNodeValue();

    // get node type (node type will be TEXT_NODE)
    type = textNode->GetNodeType();

    // get next sibling node (next of "name")
    node = node->GetNextSibling();

    // get node name (resultString will be "size")
    resultString = node->GetNodeName();

    // get node type (node type will be ELEMENT_NODE)
    type = node->GetNodeType();
}
[Note] Note
The root node of the DOM tree is obtained by the SFXXMLDOMParser::GetDocument function, and the child node is obtained by the SFXXMLNode::GetFirstChild function.

Example 19.4. Get the multiple nodes

SFXXMLDOMParser parser;     // DOM Parser
SFCError error;             // error value
SFXAnsiString resultString; // variable to store node name

// parse XML document in file.xml
if ((error = parser.Parse(SFXPath("/file.xml"))) == SFERR_NO_ERROR) {

    // get root node of DOM tree
    SFXXMLDocumentPtr root = parser.GetDocument(); 

    // get first child of root node
    SFXXMLNodePtr child = root->GetFirstChild();   

    // get all child nodes
    // SFXXMLNode::DOMNodeList is same as SFXList
    SFXXMLNode::DOMNodeListPtr nodeList = child->GetChildNodes();

    // get iterator
    SFXXMLNode::DOMNodeList::Iterator itor = nodeList->GetIterator();

    while (itor.HasNext()) { // if next node exists
        // get the "name", "size", and "color" nodes sequentially
        SFXXMLNodePtr node = itor.GetNext();

        // get node name
        resultString = node->GetNodeName();

        // get text of this node (e.g. "apple" in case of "name", "XS" in case of "size")
        resultString = node->GetText();
    }

    // get all Element nodes of which tag name match "color"
    nodeList = static_cast<SFXXMLElementPtr>(child)->GetElementsByTagName("color"); 

    itor = nodeList->GetIterator(); // get iterator

    while (itor.HasNext()) {             // while next Element node exists
        SFXXMLNodePtr node = itor.GetNext(); // get next Element node
        // ...
    }
}
[Note] Note
The SFXXMLNode::GetChildNodes function is used to get all the child nodes.
[Note] Note
The result is returned as type of "pointer to SFXXMLNode::DOMNodeList". This type is same as SFXList<SFXXMLNodePtr>.

Example 19.5. XML document to be parsed (file.xml)

<fruits>
    <fruit>
        <name>apple</name>
        <size>XS</size>
        <color>red</color>
    </fruit>
    <fruit>
        <name>banana</name>
        <size>S</size>
        <color>yellow</color>
    </fruit>
    <fruit>
        <name>melon</name>
        <size>XS</size>
        <color>green</color>
    </fruit>
</fruits>

Example 19.6. Process the each element

SFXXMLDOMParser parser; // DOM Parser
SFCError error;         // error value

// parse XML document in file.xml
if ((error = parser.Parse(SFXPath("/file.xml"))) == SFERR_NO_ERROR) {

    // get root node of DOM tree
    SFXXMLDocumentPtr root = parser.GetDocument(); 

    // get first child node of root node, i.e., "fruits" node
    SFXXMLNodePtr child = root->GetFirstChild();  

    // get first child of "fruits" node, i.e., "fruit" node
    SFXXMLNodePtr node = child->GetFirstChild();   

    // process each child node of "fruit" node
    while (node != null) {

        SFXXMLNodePtr nameNode = node->GetFirstChild();   // get first child: node, i.e., "name" node

        SFXAnsiString resultString = nameNode->GetText(); // get text of this node

        node = node->GetNextSibling(); // get next sibling node

    }
}
[Note] Note
If two or more sibling nodes exist, the SFXXMLNode::GetNextSibling function is used to get the sibling nodes one after another.

Example 19.7. The XML file to be parsed (file.xml)

<fruit>
    <name language="english" code="ascii">apple</name>
    <size>XS</size>
    <color>red</color>
</fruit>

Example 19.8. Get the attributes

SFXXMLDOMParser parser;     // DOM Parser
SFCError error;             // Error value
SFXAnsiString resultString; // variable to store value of attribute

// parse XML document stored in file.xml
if ((error = parser.Parse(SFXPath("/file.xml"))) == SFERR_NO_ERROR) {

    // get root node of DOM tree
    SFXXMLDocumentPtr root = parser.GetDocument(); 

    // get first child of root node
    SFXXMLNodePtr child = root->GetFirstChild();   
    
    child = child->GetFirstChild();

    // if name of child node is "name"
    if (SFXAnsiString("name").Equals(child->GetNodeName())) {

        // cast into Element node to get Attribute node
        SFXXMLElementPtr element = static_cast<SFXXMLElementPtr>(child);

        // get value of Attribute node of which name is "language" from this Element node
        // resultString will be "english"
        resultString = element->GetAttribute("language");

        // get Attribute node of which name is "language"
        SFXXMLAttributePtr attr = element->GetAttributeNode("language");
        
        // get value of this Attribute node
        resultString = attr->GetNodeValue();
        
        // get all Attribute nodes of this Element node
        SFXXMLNode::DOMNamedNodeMapPtr nodeMap = element->GetAttributes();

        // get Attribute node of which name is "code" from nodeMap
        attr = static_cast<SFXXMLAttributePtr>(nodeMap->GetNamedItem("code"));

        // get value of this Attribute node
        resultString = attr->GetNodeValue();
    }
}
[Note] Note
SFXXMLElement::GetAttribute function is used to get the value of Attribute node by name.

Generate the XML Document

To generate the XML Document, use the SFXXMLDocument class, the SFXXMLElement class, etc. as follows:

  1. Create the root node of the DOM tree(instance of SFXXMLDocument class).
  2. Create the Element node(instance of SFXXMLElement class), which will be the root element of the XML document.
  3. Append the Element node created in the Step 2. on the root node created in the Step 1. as its first child node.
  4. Create the DOM nodes if necessary, which inherit from the SFXXMLNode class excluding the SFXXMLDocument class.
  5. Some nodes can be set information such as name, value, attributes, etc.
  6. Construct the DOM tree with the root node, Element node which is the root element of the XML document, and the DOM nodes created in the Step 4. and 5.
  7. Finally, call the SFXXMLDocument::Save function, and then save the DOM tree as a file of the XML document.

Example 19.9. Generate the XML Document

SFCError error; // Error value

// create XML document as document node(root node of DOM tree)
SFXXMLDocument document;

// set XML document property
document.SetVersion("1.0");

// create COLLECTION element as collection node
SFXXMLElementPtr collection = document.CreateElement("COLLECTION");
if (collection == null) {
    return;
}

// add collection node to document node
error = document.AppendChild(SFXXMLNodePtr(collection));
if (error != SFERR_NO_ERROR) {
    return;
}

// add attribute to collection node
collection->SetAttribute("xmlns:dt", "urn:schemas-microsoft-com:datatypes");

// create DATE element as date node
SFXXMLElementPtr date = document.CreateElement("DATE");
if (date == null) {
    return;
}

// append attribute to date node
date->SetAttribute("dt:dt", "datetime");

// append text information to date node
error = date->AppendChild(SFXXMLNodePtr(
    document.CreateTextNode("1998-10-13T15:56:00")));
if (error != SFERR_NO_ERROR) {
    return;
}

// append date node to collection node
error = collection->AppendChild(SFXXMLNodePtr(date));
if (error != SFERR_NO_ERROR) {
    return;
}

// create BOOK element as book node
SFXXMLElementPtr book = document.CreateElement("BOOK");
if (book == null) {
    return;
}

// append book node to collection node
error = collection->AppendChild(SFXXMLNodePtr(book));
if (error != SFERR_NO_ERROR) {
    return;
}

// create "<TITLE>Cosmos</TITLE>"
element = document.CreateElement("TITLE");
if (element == null) {
    return;
}

error = element->AppendChild(SFXXMLNodePtr(document.CreateTextNode("Cosmos")));
if (error != SFERR_NO_ERROR) {
    return;
}

error = book->AppendChild(SFXXMLNodePtr(element));
if (error != SFERR_NO_ERROR) {
    return;
}

// create "<AUTHOR>Carl Sagan</AUTHOR>"
element = document.CreateElement("AUTHOR");
if (element == null) {
    return;
}

error = element->AppendChild(SFXXMLNodePtr(document.CreateTextNode("Carl Sagan")));
if (error != SFERR_NO_ERROR) {
    return;
}

error = book->AppendChild(SFXXMLNodePtr(element));
if (error != SFERR_NO_ERROR) {
    return;
}

// create "<PUBLISHER>Ballantine Books</PUBLISHER>"
element = document.CreateElement("PUBLISHER");
if (element == null) {
    return;
}

error = element->AppendChild(SFXXMLNodePtr(document.CreateTextNode("Ballantine Books")));
if (error != SFERR_NO_ERROR) {
    return;
}

error = book->AppendChild(SFXXMLNodePtr(element));
if (error != SFERR_NO_ERROR) {
    return;
}

// save XML document
error = document.Save("book.xml");
if (error != SFERR_NO_ERROR) {
    return;
}

Example 19.10. Execution Result

<?xml version='1.0'?>
<COLLECTION
   xmlns:dt="urn:schemas-microsoft-com:datatypes">
  <DATE dt:dt="datetime">1998-10-13T15:56:00</DATE>
  <BOOK>
    <TITLE>Cosmos</TITLE>
    <AUTHOR>Carl Sagan</AUTHOR>
    <PUBLISHER>Ballantine Books</PUBLISHER>
  </BOOK>
</COLLECTION>
[Caution] Using the Emulator

The "book.xml" file will not be generated if its size exceeds the Emulator file system capacity.

19.7.2. XML SAX Parser

SAX (SFXXMLSAXParser) is the event-driven parser. When parsing a XML document from its head, SAX parser generates an event each time a tag or an attribute appears. The users should register the function (the handler) that executes when an event is generated to the SAX parser.

The handler class that inherits from SFXXMLDefaultHandler is defined, then the handler is registered to the SAX parser.

Example 19.11. XML document to be parsed (file.xml)

<fruit>
  <name>apple</name>
  <size>XS</size>
  <color>red</color>
</fruit>

Example 19.12. Define and implement the handler class

// handler class
class MyXMLHandler : public SFXXMLDefaultHandler {
public:
    explicit MyXMLHandler(Void);
    virtual ~MyXMLHandler(Void);

    // declaration for each handler

    // handlers for obtaining content of XML document
    virtual Void Characters(SFXAnsiStringConstRef string, BoolConst cdataSection = true);
    virtual Void EndDocument(Void);
    virtual Void EndElement(SFXAnsiStringConstRef uri = SFXAnsiString::EmptyInstance(), SFXAnsiStringConstRef localname = SFXAnsiString::EmptyInstance(), SFXAnsiStringConstRef qname = SFXAnsiString::EmptyInstance());
    virtual Void StartDocument(Void);
    virtual Void StartElement(SFXAnsiStringConstRef uri, SFXAnsiStringConstRef localname, SFXAnsiStringConstRef qname, SFXXMLGrammar::XMLAttrListConstRef attrList);
    virtual Void IgnorableWhitespace(SFXAnsiStringConstRef string);
    virtual Void ProcessingInstruction(SFXAnsiStringConstRef target, SFXAnsiStringConstRef data);
    virtual Void EndPrefixMapping(SFXAnsiStringConstRef  prefix);
    virtual Void StartPrefixMapping(SFXAnsiStringConstRef prefix, SFXAnsiStringConstRef uri);
 
   // handlers for parsing XML document
    virtual Void Comment(SFXAnsiStringConstRef string);
    virtual Void EndCDATA(Void);
    virtual Void EndDTD(Void);
    virtual Void EndEntity(SFXAnsiStringConstRef name);
    virtual Void StartCDATA(Void);
    virtual Void StartDTD(SFXAnsiStringConstRef name, SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId);
    virtual Void StartEntity(SFXAnsiStringConstRef name);

   // handlers for processing DTD
    virtual Void NotationDecl(SFXAnsiStringConstRef name, SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId);
    virtual Void UnparsedEntityDecl(SFXAnsiStringConstRef name, SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId, SFXAnsiStringConstRef notationName);

   // handlers to be notified of having received each declaration
    virtual Void ElementDecl(SFXAnsiStringConstRef name, SFXAnsiStringConstRef model);
    virtual Void AttributeDecl(SFXAnsiStringConstRef ename, SFXAnsiStringConstRef aname, SFXAnsiStringConstRef type, SFXAnsiStringConstRef valuedefault, SFXAnsiStringConstRef value);
    virtual Void InternalEntityDecl(SFXAnsiStringConstRef name, SFXAnsiStringConstRef value);
    virtual Void ExternalEntityDecl(SFXAnsiStringConstRef name, SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId);

   // handlers to be notified of having received error message
    virtual Void ErrorReport(SFCErrorConst error, SFXAnsiStringConstRef errInfo);
};

// constructor
MyXMLHandler::MyXMLHandler(Void)
{
    return;
}

// destructor
MyXMLHandler::~MyXMLHandler(Void)
{
    return;
}

// handler to receive the notification of the start of a document
Void MyXMLHandler::StartDocument(Void)
{
    TRACE("document start");
}

// handler to receive the notification of the end of a document
Void MyXMLHandler::EndDocument(Void)
{
    TRACE("document end");
}

// handler to receive the notification of the start of an element
Void MyXMLHandler::StartElement(SFXAnsiStringConstRef uri,
    SFXAnsiStringConstRef localname, SFXAnsiStringConstRef qname,
    SFXXMLGrammar::XMLAttrListConstRef attrList)
{
    // display name of the element
    TRACE("element: %s start", qname.GetCString());

    // get enumerator for first attribute of the element
    SFXXMLGrammar::XMLAttrList::Enumerator etor = attrList.GetFirstEnumerator();
    
    // display each name and its value of attributes
    while (etor.HasNext()) {
        SFXXMLGrammar::LPXMLATTR attr = etor.GetNext();     // gete next attribute
        
        TRACE("attrname: %s", attr->_attName.GetCString());  // display name of attribute
        TRACE("attrvalue: %s", attr->_value.GetCString());   // display value of attribute
    }

}

// handler to receive the notification of the end of an element
Void MyXMLHandler::EndElement(SFXAnsiStringConstRef uri,
    SFXAnsiStringConstRef localname, SFXAnsiStringConstRef qname)
{
    TRACE("element: %s end", qname.GetCString());
}

// handler to receive the notification of a character data
Void MyXMLHandler::Characters(SFXAnsiStringConstRef string,
    BoolConst /*cdataSection*/)
{
    TRACE("text: %s", string.GetCString());
    return;
}

// following are empty handlers (must be defined even if event is ignored)

// handler to receive the notification of a unnecessary white space
Void MyXMLHandler::IgnorableWhitespace(SFXAnsiStringConstRef string)
{
    return;
}

// handler to receive the notification of a processing instruction
Void MyXMLHandler::ProcessingInstruction(SFXAnsiStringConstRef target,
    SFXAnsiStringConstRef data)
{
    return;
}

// handler to receive the notification of the end of a mapping between prefix and namespace URI
Void MyXMLHandler::EndPrefixMapping(SFXAnsiStringConstRef  prefix)
{
    return;
}

// handler to receive the notification of the start of a mapping between prefix and namespace URI
Void MyXMLHandler::StartPrefixMapping(SFXAnsiStringConstRef  prefix,
    SFXAnsiStringConstRef uri)
{
    return;
}

// handler to receive the notification of a comment
Void MyXMLHandler::Comment(SFXAnsiStringConstRef string)
{
    return;
}

// handler to receive the notification of the end of a CDATA section
Void MyXMLHandler::EndCDATA(Void)
{
    return;
}

// handler to receive the notification of the end of a DTD declaration
Void MyXMLHandler::EndDTD(Void)
{
    return;
}

// handler to receive the notification of the end of an entity
Void MyXMLHandler::EndEntity(SFXAnsiStringConstRef name)
{
    return;
}

// handler to receive the notification of the start of a CDATA section
Void MyXMLHandler::StartCDATA(Void)
{
    return;
}

// handler to receive the notification of the start of a DTD declaration
Void MyXMLHandler::StartDTD(SFXAnsiStringConstRef name,
    SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId)
{
    return;
}

// handler to receive the notification of the start of an entity
Void MyXMLHandler::StartEntity(SFXAnsiStringConstRef name)
{
    return;
}

// handler to receive the notification of a notation declaration
Void MyXMLHandler::NotationDecl(SFXAnsiStringConstRef name,
    SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId)
{
    return;
}

// handler to receive the notification of the declaration of an unparsed entity
Void MyXMLHandler::UnparsedEntityDecl(SFXAnsiStringConstRef name,
    SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId,
    SFXAnsiStringConstRef notationName)
{
    return;
}

// handler to receive the notification of an element type declaration
Void MyXMLHandler::ElementDecl(SFXAnsiStringConstRef name,
    SFXAnsiStringConstRef model)
{
    return;
}

// handler to receive the notification of an ATTLIST declaration
Void MyXMLHandler::AttributeDecl(SFXAnsiStringConstRef ename,
    SFXAnsiStringConstRef aname, SFXAnsiStringConstRef type,
    SFXAnsiStringConstRef mode, SFXAnsiStringConstRef value)
{
    return;
}

// handler to receive the notification of an internal entity declaration
Void MyXMLHandler::InternalEntityDecl(SFXAnsiStringConstRef name,
    SFXAnsiStringConstRef value)
{
    return;
}

// handler to receive the notification of an external entity declaration
Void MyXMLHandler::ExternalEntityDecl(SFXAnsiStringConstRef name,
    SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId)
{
    return;
}

// handler to receive the notification of an error
Void MyXMLHandler::ErrorReport(SFCErrorConst error,
    SFXAnsiStringConstRef errInfo)
{
    return;
}

Example 19.13. Function of Using SAX Parser

SFCError error;
SFXXMLSAXParser parser;
MyXMLHandler handler;

// set handler
parser.SetDefaultHandler(&handler);

// parse XML document
error = parser.Parse(SFXPath("/file.xml"));

TRACE("parse end");

Example 19.14. Execution Result

document start
element: fruit start
element: name start
text: apple
element: name end
element: size start
text: XS
element: size end
element: color start
text: red
element: color end
element: fruit end
document end
parse end

Next, each element will be stored in the SFXProperty.

Example 19.15. XML document to be parsed (file.xml)

<fruits>
  <fruit>
    <name>apple</name>
    <size>XS</size>
    <color>red</color>
  </fruit>
  <fruit>
    <name>grape</name>
    <size>SS</size>
    <color>purple</color>
  </fruit>
  <fruit>
    <name>peach</name>
    <size>M</size>
    <color>pink</color>
  </fruit>
  <fruit>
    <name>pineapple</name>
    <size>LL</size>
    <color>yellow</color>
  </fruit>
</fruits>

Example 19.16. Define and Implement the handler class

// handler class
class MyXMLHandler : public SFXXMLDefaultHandler {
private:
    // class to store pairs of the elements
    SFXProperty _property;
    // variable to temporarily keep tag name
    SFXAnsiString _name;
    // variable to temporarily keep tag size
    SFXAnsiString _size;
    // tag kinds
    enum KindOfTag {NOTHING, NAME, SIZE, COLOR};
    // kind of tag being parsed
    KindOfTag _kind;
public:
    // hereafter, processing is similar to implementation of XML SAX handler class

};

// constructor
MyXMLHandler::MyXMLHandler(Void)
{
    _kind = NOTHING;
    return;
}

// handler that takes element starting notification
Void MyXMLHandler::StartElement(SFXAnsiStringConstRef uri,
    SFXAnsiStringConstRef localname, SFXAnsiStringConstRef qname,
    SFXXMLGrammar::XMLAttrListConstRef attrList)
{
    if (qname.Equals("name")) { 
        // if tag name is "name"
        _kind = NAME; // show tag name being parsed
    }
    else if (qname.Equals("size")) {
        _kind = SIZE;
    }
    else if (qname.Equals("color")) {
        _kind = COLOR;
    }
    return;
}

// handler that takes element ending notification
Void MyXMLHandler::EndElement(SFXAnsiStringConstRef uri,
    SFXAnsiStringConstRef localname, SFXAnsiStringConstRef qname)
{
    if (qname.Equals("fruit")) { 
        // if fruit tag ends
        // store text in _name and _size
        _property.Append(_name, _size);
    }
    _kind = NOTHING;
    return;
}

// handler that takes character data notification
Void MyXMLHandler::Characters(SFXAnsiStringConstRef string, BoolConst /*cdataSection*/)
{
    switch (_kind) {
        case NAME: // name is being parsed
            _name = string; // store text in _name
            break;
        case SIZE:
            _size = string;
            break;
        default:
            break;
    }
    return;
}

The name and size pair of each XML sentence is created then stored in SFXProperty

19.7.3. Parsing a XML Document with DTD

Example 19.17. XML Document to be parsed (file.xml)

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE Mail SYSTEM "personal.dtd">
<Mail>
  <From>&name;</From>
  <To>Receiver</To>
  <Cc>&Email;</Cc>
  <Date> Thu, 7 Oct 1999 11:15:16 -0600</Date>
  <Subject>XML Introduction</Subject>
  <Body>Comments:<P align = "right">Thanks for reading<br/>this article</P>
    <br/>
    <P>Hope you enjoyed this article</P>
    <P>&copyright;</P>
  </Body>
</Mail>

Example 19.18. DTD file for verification (personal.dtd)

<?xml encoding="ISO-8859-1"?>

<!-- @version: 10.1-->

<!ELEMENT Mail (From, To, Cc?, Date?, Subject, Body)>
<!ELEMENT From (#PCDATA)>
<!ELEMENT To (#PCDATA)>
<!ELEMENT Cc (#PCDATA)>
<!ELEMENT Date (#PCDATA)>
<!ELEMENT Subject (#PCDATA)>
<!ELEMENT Body (#PCDATA | P | Br)*>
<!ELEMENT P (#PCDATA | br)*>
<!ATTLIST P align (left | right | justify) "left">
<!ELEMENT br EMPTY>
<!ENTITY  name "sophia">
<!ENTITY  Email "&name;@s-cradle.com">
<!ENTITY  copyright "Copyright (C) 2005 - 2006 Sophia Cradle Incorporated.">

Example 19.19. Parse the XML document with DTD

SFXXMLDOMParser parser;
SFCError error;

// set grammar type to parse XML document with DTD
parser.SetGrammar(SFXXMLGrammar::GRAMMAR_DTD);

// set to validate XML document with DTD
parser.SetValidationDTD(true);

// set to read external DTD file
parser.SetLoadExternalDTD(true);

// parse XML document  with DTD using DOM parser
error = parser.Parse(SFXPath("/file.xml"));

if (error == SFERR_NO_ERROR) {
    // get root node of DOM tree
    SFXXMLDocumentPtr root = parser.GetDocument();

    // get DocumentType node
    SFXXMLDocumentTypePtr documentType = root->GetDocumentType();

    // get system identifier of external DTD subset
    // id will be "personal.dtd"
    SFXAnsiString id = documentType->GetSystemID();

    // get Entity nodes defined in DTD as DOMNamedNodeMap
    SFXXMLNode::DOMNamedNodeMapPtr entitymap = documentType->GetEntities();

    // get value of the "name" entity
    // it will be "sophia"
    SFXAnsiString name = SFXXMLEntityPtr(entitymap->
        GetNamedItem("name"))->GetValue();
}

19.7.4. Parsing a XML Document with XML Schema

Example 19.20. Sample code of parsing the XML document with XML Schema

SFXXMLDOMParser parser;

// set to create comment node
parser.SetCreateCommentNodes(true);

// set to process namespace
parser.SetDoNamespaces(true);

// set grammar type to parse XML document with Schema
parser.SetGrammar(SFXXMLGrammar::GRAMMAR_SCHEMA);

// set to process XML Schema
parser.SetDoSchema(true);

// set XSD file for XML document with XML Schema
// default directory is home directory of application
parser.SetSchemaLocation("schema.xsd");

// set to validate XML document with XML Schema
parser.SetValidationSchema(true);

// set to ignore annotations
parser.SetIgnoreAnnotations(false);

// parse XML document with XML Schema using DOM parser
error = parser.Parse(SFXPath("/file.xml"));

19.7.5. SOAP

Example 19.21. Create the SOAP message

SFXSOAPWriter soapwriter;   // variable to generate each element of the SOAP message
SFCError      error;        // variable to store error value

// create Envelope element
// namespace prefix: "SOAP-ENV" by default
// SOAP Message Version: SFXSOAPParser::SOAP_VERSION_1_2 ("http://www.w3.org/2003/05/soap-envelope") or
//                       SFXSOAPParser::SOAP_VERSION_1_1 ("http://schemas.xmlsoap.org/soap/envelope/") 
// SOAP encoding: "STANDARD "("http://schemas.xmlsoap.org/soap/encoding/" ) or 
//                "NONE "(No SOAP encoding is set)
SFXXMLElementPtr envelope = soapwriter.SetEnvelope("env", SFXSOAPParser::SOAP_VERSION_1_2, "STANDARD ");


// create Header and Body elements
if (envelope) {

    // add namespace xmlns:m= "http://www.example.org/timeouts"
    error = soapwriter.AddNamespace(envelope, "m", "http://www.example.org/timeouts");
    // confirm whether namespace has been added or not
    if(error != SFERR_NO_ERROR){
         TRACE("-----Envelope_NAMESPACE_ERROR:%d-----", error);
    }
    // set SOAP Fault element consisted of faultcode, faultstring, and faultactor elements (by default, it is the child element of Body element)
    soapwriter.SetFault("testing-fault-code","testing-fault-string","testing-fault-actor");

    // set detail element to SOAP Fault element
    soapwriter.SetFaultDetail("STANDARD")->SetText("testing-fault-detail-message");

    // set Header element
    SFXXMLElementPtr header = soapwriter.SetHeader();

    if (header) {
        // add attribute of isbn:bookname="The Football World Cup"
        error = soapwriter.AddAttribute(header, "bookname", "http://www.example.com/ISBN", "The Football World Cup", "isbn");
        // confirm whether attribute has been added or not
        if(error != SFERR_NO_ERROR){
            TRACE("-----HEADER_ATTRIBUTE_ERROR:%d-----", error);
        }
           
        // add namespace xmlns:isbn="http://www.example.com/ISBN"
        error = soapwriter.AddNamespace(header, "isbn", "http://www.example.com/ISBN");
        // confirm whether namespace has been added or not
        if(error != SFERR_NO_ERROR){
            TRACE("-----HEADER_NAMESPACE_ERROR:%d-----", error);
        }

        // add Upgrade element as child element of Header element
        // namespace of Upgrade element is the same as that of Header element
        SFXXMLElementPtr elem = soapwriter.SetElement(header, "Upgrade", header->GetNamespaceURI(), header->GetPrefix());

        if (elem) {
            // set SupportedEnvelope element as child element of Upgrade element
            elem = soapwriter.SetElement(elem, "SupportedEnvelope", header->GetNamespaceURI(), header->GetPrefix());

            // add attribute of SupportedEnvelope element
            error = soapwriter.AddAttribute(elem, "qname", "http://schemas.xmlsoap.org/soap/envelope/", "ns1:Envelope");
            // confirm whether attribute has been added or not
            if(error != SFERR_NO_ERROR){
                TRACE("-----UPGRADE_ATTRIBUTE_ERROR:%d-----", error);
            }
                
            // add namespace of SupportedEnvelope element
            error = soapwriter.AddNamespace(elem, "ns1", "http://schemas.xmlsoap.org/soap/envelope/");   
            // confirm whether namespace has been added or not
            if(error != SFERR_NO_ERROR){
                TRACE("-----UPGRADE_NAMESPACE_ERROR:%d-----", error);
            }
        }
    }

    // save SOAP message created
    error = soapwriter.Save("soapwriter.xml");

    // confirm SOAP message has been stored or not
    if(error != SFERR_NO_ERROR){
        TRACE("-----SOAP_SAVE_ERROR:%d-----", error);
    }

}

Example 19.22. Execution Result

<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"
              env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
              xmlns:m="http://www.example.org/timeouts">
    <env:Header isbn:bookname="The Football World Cup" xmlns:isbn="http://www.example.com/ISBN">
        <env:Upgrade>
            <env:SupportedEnvelope qname="ns1:Envelope" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/"/>
        </env:Upgrade>
    </env:Header>
    <env:Body>
        <env:Fault>
            <faultcode>testing-fault-code</faultcode>
            <faultstring>testing-fault-string</faultstring>
            <faultactor>testing-fault-actor</faultactor>
            <detail env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">testing-fault-detail-message</detail>
        </env:Fault>
    </env:Body>
</env:Envelope>

Table 19.16. SOAP Error Message

Value Description
0x699F There is no Envelope element in the SOAP message.
0x69A0 There is no Body element in the SOAP message.
0x69A1 There is no Fault element in the SOAP message.
0x69A2 There is a duplicate Envelope element in the SOAP message.
0x69A3 There is an invalid element in the SOAP message.
0x69A4 The specified SOAP version is not supported.
0x69A5 The message is Fault in the SOAP messaget.
0x0106 There is not enough space in the file system (this may occur when the XML document is being created)
[Note] XML Error Message

Reference: SFCErrorEnum

Example 19.23. Call Web Service using the SOAP-RPC Protocol

#define AMAZON_ID " // Amazon ID must be set

SFMTYPEDEFCLASS(SOAPTest)
class SOAPTest : public SFCApplication {
    SFMSEALCOPY(SOAPTest)
private:
    SFXSOAPRPC _rpc;    // variable for processing the SOAP-RPC protocol

    Void OnSOAP(Void);
    static Void OnResultSHP_SOAP(SFCError error, const SFXSOAPRPC::Params& result, const SFXSOAPRPC::FAULT& fault, SFXSOAPParserConstRef soap, VoidPtr reference);
    Void OnResult_SOAP(SFCError error, const SFXSOAPRPC::Params& result, const SFXSOAPRPC::FAULT& fault, SFXSOAPParserConstRef soap);
};

Void SOAPTest::OnSOAP()
{
    // set method name
    _rpc.SetMethodName("ItemSearch");
    
    // set SOAP encoding
    _rpc.SetEncodingStyle("http://schemas.xmlsoap.org/soap/encoding/");
    // the following code is the same as the above
	// _rpc.SetEncodingStyle("STANDARD");

    // set target URI
    _rpc.SetTargetObjectURI("https://webservices.amazon.com/");

    // set parameters of web service
    _rpc.AddParameter("AWSAccessKeyId", 
                      SFXBuffer(SFXAnsiString(AMAZON_ID)));
    _rpc.AddParameter("Keywords", 
                      SFXBuffer(SFXAnsiString("caviar")));
    _rpc.AddParameter("MerchantId", 
                      SFXBuffer(SFXAnsiString("Amazon")));
    _rpc.AddParameter("SearchIndex", 
                      SFXBuffer(SFXAnsiString("GourmetFood")));

    // call web service
    _rpc.Invoke("http://soap.amazon.co.jp/onca/soap?Service=AWSECommerceService",
                "http://soap.amazon.com",
                OnResultSHP_SOAP,
                this);
}

// callback function to be notified of the result of the web service
// error: error value, result: return value of web service, fault: SOAP Fault element, soap : SOAP message, reference: data passed to callback function
Void SOAPTest::OnResultSHP_SOAP(SFCError error, const SFXSOAPRPC::Params& result, const SFXSOAPRPC::FAULT& fault, SFXSOAPParserConstRef soap, VoidPtr reference)
{
    static_cast<SOAPTestPtr>(reference)->OnResult_SOAP(error, result, fault, soap);
}

// Function to process the SOAP message received from web server
Void SOAPTest::OnResult_SOAP(SFCError error, const SFXSOAPRPC::Params& result, const SFXSOAPRPC::FAULT& fault, SFXSOAPParserConstRef soap)
{
    if (error == SFERR_NO_ERROR) {

        // get result of the SOAP message(SFXSOAPRPC::Params array) for each parameter

        // get enumerator
        SFXSOAPRPC::Params::Enumerator paramEtor = result.GetFirstEnumerator();

        while (paramEtor.HasNext()) {

            // get each parameter
            SFXSOAPRPC::LPPARAMETER temp = paramEtor.GetNext();

            // display name of parameter
            TRACE("parameter-name: %s", temp->_name.GetCString());
            // display type of parameter
            TRACE("parameter-type: %d", temp->_type);

            if (!temp->_value.IsEmpty()) {

                // display value of parameter
                TRACE("parameter-value: %s", ACharConstPtr(temp->_value.GetBuffer()));
            }
        }
   }
   // display error message(SOAP Fault)
   else if (error == SFERR_SOAP_FAULT_MESSAGE) {

        if(!fault._faultactor.IsEmpty()) {

            // if faultactor element is not empty, display its content
            TRACE("faultactor: %s", fault._faultactor.GetCString());    
        }

        if(!fault._faultcode.IsEmpty()) { 

            // if faultcode element is not empty, display its content
            TRACE("faultcode: %s", fault._faultcode.GetCString());     
        }

        if(!fault._faultstring.IsEmpty()) {

            // if faultstring element is not empty, display its content
            TRACE("faultstring: %s", fault._faultstring.GetCString());
        }

        if (!fault._faultdetail) {

             // if detail element is not "null", display its content
            TRACE("faultstring: %s", fault._faultdetail->GetText().GetCString());
        }
    }
    return;
}