BDE 4.14.0 Production release
|
Provide the properties of an attribute in an XML element tag.
This component provides a class, balxml::ElementAttribute
, that encapsulates the name, namespace, and value of an attribute within an element in an XML document, along with a flag indicating whether the value comes from the default value in the document's schema. There are accessors to return the attribute name as a qualified name, namespace prefix, namespace URI, namespace ID (in a namespace registry), and local name (without the prefix).
If a namespace prefix stack and a qualified name are provided at construction (or via the reset
method), then all of the other facets of the name can be computed automatically. For efficiency reasons, these various decompositions of the attribute name are computed only when needed and cached within the balxml::ElementAttribute
structure. The caller can supply any or all of these computed facets in the constructor or reset
method. Explicitly supplying a facet prevents it from being computed, thus saving processing time. If the object is constructed with explicit values for all facets of the name, then the prefix stack is never used and may be null. If an explicitly-supplied facet differs from the value that would have been computed otherwise, then the facets returned by the accessors will be inconsistent with one-another. This inconsistency is deliberately permitted so that an program may construct a balxml::ElementAttribute
even when some parts of the name are not yet known, e.g., if the prefix URI is known but the qualified name is not. If the qualified name facet is zero, then no other facets will be computed – their original values will be returned from the accessors.
balxml::ElementAttribute
is not a value-semantic class. It provides copy construction and assignment, but does not provide equality or persistence operators. Copying a balxml::ElementAttribute
object copies all of its pointer facets but does not make copies of the pointed-to strings or objects. The presence of copy operations makes it possible to use balxml::ElementAttribute
with container class templates.
A balxml::ElementAttribute
object does not own any of its pointer facets and it performs no memory management. This means that a balxml::ElementAttribute
object can be invalidated by modifying or deleting any of the pointed-to entities. Calling an accessor on an invalid balxml::ElementAttribute
is unsafe because the accessor may return an invalid pointer. However an invalid object may be safely destroyed or reset. Components that set or return a balxml::ElementAttribute
object should provide clear documentation describing the events that will cause the resulting balxml::ElementAttribute
object to become invalid (see balxml::Reader
).
It is safe to access or modify two balxml::ElementAttribute
objects simultaneously, each from a separate thread. It is safe to access a single balxml::ElementAttribute
object simultaneously from two or more separate threads, provided no other thread is simultaneously modifying the object. It is not safe to access or modify a balxml::ElementAttribute
object in one thread while another thread modifies the same object.
A balxml::ElementAttribute
object holds pointers to objects that it does not own and which can be modified independently of the balxml::ElementAttribute
object. It is not safe to modify or delete any of these object in one thread while accessing or modifying the balxml::ElementAttribute
object in another thread.
This section illustrates intended use of this component.
The following function parses an XML-style attribute assignment in the form "qname=`value`", where qname
can be a qualified name in the form, "prefix:localName". The prefix (if any) must be registered in the specified prefixStack
object. Either single or double quotes may be used to enclose the attribute value. The parsed attribute is stored in the specified attribute
object of type balxml::ElementAttribute
. Note that this function modifies the input string by inserting null characters, rather than copying the component parts into allocated memory. This is a realistic interface for a function used within an XML parser that has already copied the XML stream into allocated memory. Also note that this function does not interpret character escapes such as "&".
First, find the end of the qualified name, i.e., the =
character:
Then find out which quote character is used to start the value string
The value string starts after the opening quote and extends until a matching quote:
Once we have successfully parsed the string, chop it into pieces by putting a null terminator at the end of the qualified name and at the end of the value string:
Use the prefix stack, qname, and value to set the attribute object. All other arguments are defaulted and will be computed as needed.
Before calling the parseAttribute
function, it is necessary to create a namespace registry and prefix stack, as well as to register one or more prefixes:
Now we can parse an attribute string and the balxml::ElementAttribute
object will provide detailed information about it.
Results are slightly different when the attribute name has no prefix:
As per the XML namespace standard, an attribute with no namespace prefix does NOT inherit the default namespace but rather has NO namespace:
A balxml::ElementAttribute
does not need to be generated by parsing XML code. If a specific facet of the object is set to a non-null value, then that value will be returned by the corresponding accessor even if it is inconsistent with the other values in the object. For example, the following constructs a valid balxml::ElementAttribute
object, even though the prefix value does not agree with the qualified name:
There is no consistency checking, and the mismatched prefix is simply returned by the accessor:
Note that the ability to create inconsistent objects is a deliberate feature. It allows parsers to construct balxml::Attribute
objects before all information is known, e.g., before the namespace is registered with the prefix stack. Consistency checking also reduces performance.