BDE 4.14.0 Production release
Loading...
Searching...
No Matches
balxml_minireader

Detailed Description

Outline

Purpose

Provide light-weight implementation of balxml::Reader protocol.

Classes

See also
balxml_reader, balxml_errorinfo

Description

The balxml::MiniReader class is a light-weight implementation of balxml::Reader interface. The API acts as a currentNode going forward on the document stream and stopping at each node in the way. The current node refers to the node on which the reader is positioned. The user's code keeps control of the progress and simply calls a read function repeatedly to progress to each node in sequence in document order. This provides a far more standard, easy to use and powerful API than the existing SAX.

Data Validation


The balxml::MiniReader class is not a validating reader (balxml::ValidatingReader). As a result while parsing data it does not make an attempt to ensure the correctness of either the data or the structure of the incoming XML. The class accepts characters as element data that the XML standard considers invalid. For example the & and < characters in element data will parse without error. Similarly, it does not return an error if the read data does not conform to its specified schema. To get stricter data validation, clients should use a concrete implementation of a validating reader (such as a_xercesc::Reader) instead.

Usage

This section illustrates intended use of this component.

Example 1: Basic Usage

For this example, we will use balxml::MiniReader to read each node in an XML document. We do not care about whitespace, so we use the following utility function to skip over any whitespace nodes. This makes our example more portable to other implementations of the balxml::Reader protocol that handle whitespace differently from balxml::MiniReader.

int advancePastWhiteSpace(balxml::Reader& reader) {
const char *whiteSpace = "\n\r\t ";
const char *value = '\0';
int type = 0;
int rc = 0;
do {
rc = reader.advanceToNextNode();
value = reader.nodeValue();
type = reader.nodeType();
} while(0 == rc &&
bsl::strlen(value) == bsl::strspn(value, whiteSpace)));
assert( reader.nodeType() !=
return rc;
}
Definition balxml_reader.h:835
virtual int advanceToNextNode()=0
virtual NodeType nodeType() const =0
virtual const char * nodeValue() const =0
@ e_NODE_TYPE_TEXT
Definition balxml_reader.h:846
@ e_NODE_TYPE_WHITESPACE
Definition balxml_reader.h:856

The main program parses an XML string using the TestReader

int main()
{

The following string describes xml for a very simple user directory. The top level element contains one xml namespace attribute, with one embedded entry describing a user.

const char TEST_XML_STRING[] =
"<?xml version='1.0' encoding='UTF-8'?>\n"
"<directory-entry xmlns:dir="
"'http://bloomberg.com/schemas/directory'>\n"
" <name>John Smith</name>\n"
" <phone dir:phonetype='cell'>212-318-2000</phone>\n"
" <address/>\n"
"</directory-entry>\n";

In order to read the XML, we first need to construct a balxml::NamespaceRegistry object, a balxml::PrefixStack object, and a TestReader object, where TestReader is a derived implementation of balxml_reader .

balxml::PrefixStack prefixStack(&namespaces);
balxml::MiniReader miniReader; balxml::Reader& reader = miniReader;
assert(!reader.isOpen());
Definition balxml_minireader.h:343
Definition balxml_namespaceregistry.h:181
Definition balxml_prefixstack.h:137
virtual bool isOpen() const =0

The reader uses a balxml::PrefixStack to manage namespace prefixes so we need to set it before we call open.

reader.setPrefixStack(&prefixStack);
assert(reader.prefixStack());
assert(reader.prefixStack() == &prefixStack);
virtual void setPrefixStack(PrefixStack *prefixes)=0
virtual PrefixStack * prefixStack() const =0

Now we call the open method to setup the reader for parsing using the data contained in the in the XML string.

reader.open(TEST_XML_STRING, sizeof(TEST_XML_STRING) -1, 0, "UTF-8");
virtual int open(const char *filename, const char *encoding=0)=0

Confirm that the bdem::Reader has opened properly

assert( reader.isOpen());
assert(!bsl::strncmp(reader.documentEncoding(), "UTF-8", 5));
assert(!reader.nodeName());
assert(!reader.nodeHasValue());
assert(!reader.nodeValue());
assert(!reader.nodeDepth());
assert(!reader.numAttributes());
assert(!reader.isEmptyElement());
virtual bool isEmptyElement() const =0
virtual const char * nodeName() const =0
virtual int nodeDepth() const =0
virtual const char * documentEncoding() const =0
@ e_NODE_TYPE_NONE
Definition balxml_reader.h:844
virtual bool nodeHasValue() const =0
Return true if the current node has a value and false otherwise.
virtual int numAttributes() const =0

Advance through all the nodes and assert all information contained at each node is correct.

Assert the next node's document type is xml.

int rc = advancePastWhiteSpace(reader);
assert( 0 == rc);
assert( reader.nodeType() ==
assert(!bsl::strcmp(reader.nodeName(), "xml"));
assert( reader.nodeHasValue());
assert(!bsl::strcmp(reader.nodeValue(),
"version='1.0' encoding='UTF-8'"));
assert( reader.nodeDepth() == 1);
assert(!reader.numAttributes());
assert(!reader.isEmptyElement());
assert( 0 == rc);
assert( reader.nodeDepth() == 1);
@ e_NODE_TYPE_XML_DECLARATION
Definition balxml_reader.h:860

Advance to the top level element, which has one attribute, the xml namespace. Assert the namespace information has been added correctly to the prefix stack.

rc = advancePastWhiteSpace(reader);
assert( 0 == rc);
assert(!bsl::strcmp(reader.nodeName(), "directory-entry"));
assert(!reader.nodeHasValue());
assert( reader.nodeDepth() == 1);
assert( reader.numAttributes() == 1);
assert(!reader.isEmptyElement());
assert(!bsl::strcmp(prefixStack.lookupNamespacePrefix("dir"), "dir"));
assert(prefixStack.lookupNamespaceId("dir") == 0);
assert(!bsl::strcmp(prefixStack.lookupNamespaceUri("dir"),
"http://bloomberg.com/schemas/directory"));
@ e_NODE_TYPE_ELEMENT
Definition balxml_reader.h:845

The XML being read contains one entry describing a user, advance the users name name and assert all information can be read correctly.

rc = advancePastWhiteSpace(reader);
assert( 0 == rc);
assert(!bsl::strcmp(reader.nodeName(), "name"));
assert(!reader.nodeHasValue());
assert( reader.nodeDepth() == 2);
assert( reader.numAttributes() == 0);
assert(!reader.isEmptyElement());
rc = reader.advanceToNextNode();
assert( 0 == rc);
assert( reader.nodeHasValue());
assert(!bsl::strcmp(reader.nodeValue(), "John Smith"));
assert( reader.nodeDepth() == 3);
assert( reader.numAttributes() == 0);
assert(!reader.isEmptyElement());
rc = reader.advanceToNextNode();
assert( 0 == rc);
assert( reader.nodeType() ==
assert(!bsl::strcmp(reader.nodeName(), "name"));
assert(!reader.nodeHasValue());
assert( reader.nodeDepth() == 2);
assert( reader.numAttributes() == 0);
assert(!reader.isEmptyElement());
@ e_NODE_TYPE_END_ELEMENT
Definition balxml_reader.h:858

Advance to the user's phone number and assert all information can be read correctly.

rc = advancePastWhiteSpace(reader);
assert( 0 == rc);
assert(!bsl::strcmp(reader.nodeName(), "phone"));
assert(!reader.nodeHasValue());
assert( reader.nodeDepth() == 2);
assert( reader.numAttributes() == 1);
assert(!reader.isEmptyElement());

The phone node has one attribute, look it up and assert the balxml::ElementAttribute contains valid information and that the prefix returns the correct namespace URI from the prefix stack.

rc = reader.lookupAttribute(&elemAttr, 0);
assert( 0 == rc);
assert(!elemAttr.isNull());
assert(!bsl::strcmp(elemAttr.qualifiedName(), "dir:phonetype"));
assert(!bsl::strcmp(elemAttr.value(), "cell"));
assert(!bsl::strcmp(elemAttr.prefix(), "dir"));
assert(!bsl::strcmp(elemAttr.localName(), "phonetype"));
assert(!bsl::strcmp(elemAttr.namespaceUri(),
"http://bloomberg.com/schemas/directory"));
assert( elemAttr.namespaceId() == 0);
assert(!bsl::strcmp(prefixStack.lookupNamespaceUri(elemAttr.prefix()),
elemAttr.namespaceUri()));
rc = advancePastWhiteSpace(reader);
assert( 0 == rc);
assert( reader.nodeHasValue());
assert(!bsl::strcmp(reader.nodeValue(), "212-318-2000"));
assert( reader.nodeDepth() == 3);
assert( reader.numAttributes() == 0);
assert(!reader.isEmptyElement());
rc = advancePastWhiteSpace(reader);
assert( 0 == rc);
assert( reader.nodeType() ==
assert(!bsl::strcmp(reader.nodeName(), "phone"));
assert(!reader.nodeHasValue());
assert( reader.nodeDepth() == 2);
assert( reader.numAttributes() == 0);
assert(!reader.isEmptyElement());
Definition balxml_elementattribute.h:289
const char * prefix() const
const char * localName() const
const char * namespaceUri() const
const char * qualifiedName() const
Definition balxml_elementattribute.h:517
const char * value() const
Definition balxml_elementattribute.h:523
bool isNull() const
Definition balxml_elementattribute.h:535
virtual int lookupAttribute(ElementAttribute *attribute, int index) const =0

Advance to the user's address and assert all information can be read correctly.

rc = advancePastWhiteSpace(reader);
assert( 0 == rc);
assert(!bsl::strcmp(reader.nodeName(), "address"));
assert(!reader.nodeHasValue());
assert( reader.nodeDepth() == 2);
assert( reader.numAttributes() == 0);
assert( reader.isEmptyElement());

Advance to the end element.

rc = advancePastWhiteSpace(reader);
assert( 0 == rc);
assert( reader.nodeType() ==
assert(!bsl::strcmp(reader.nodeName(), "directory-entry"));
assert(!reader.nodeHasValue());
assert( reader.nodeDepth() == 1);
assert( reader.numAttributes() == 0);
assert(!reader.isEmptyElement());

Close the reader.

reader.close();
assert(!reader.isOpen());
return 0;
}
virtual void close()=0