Projecting Objects to XML
Specifying Namespaces for Elements and Attributes
|
|
XML elements and attributes can belong to different namespaces, and the XML Schema specification provides for multiple ways of controlling and representing namespace assignment. The
%XML.Adaptor class provides the corresponding support for your XML documents.
This section discusses the following topics:
The XML examples in this chapter are in literal
format.
This section provides a refresher on XML namespaces and an overview of how Caché objects are assigned to XML namespaces.
The general assumption in this book is that the reader is familiar with XML. It may be worthwhile, however, to review how to determine the namespace, if any, to which an element or attribute is assigned in an XML document.
First, unless the XML document includes a default namespace or a namespace prefix for every element and attribute that it includes, it is necessary to see the corresponding XML schema. Apart from any imported elements or attributes, any element or attribute is one of the following:
-
Qualified, which means that the element or attribute is in the target namespace of the schema.
-
Unqualified, which has different meaning for elements and attributes. An unqualified element is in no namespace. An unqualified attribute is in the default namespace, if any, of its containing element.
For each element and attribute that it defines, a schema indicates whether that item is qualified or unqualified. The schema does this by a combination of the following pieces:
-
These attributes are optional. The default for both of them is
"unqualified". That is, by default if a element or attribute is used without a prefix, it is in no namespace.
-
Second, the definition of an element or attribute can specify the
form attribute, which indicates how that item is assigned to a namespace. The possible values are
"qualified" and
"unqualified".
Consider the following XML document:
<?xml version="1.0" encoding="UTF-8"?>
<ClassA xmlns="mynamespace" xmlns:s01="mynamespace" s01:String1="abcdef">
<s01:ClassB xmlns="">
<String3>qrstuv</String3>
<String4>wxyz</String4>
</s01:ClassB>
<String2>ghijkl</String2>
</ClassA>
For simplicity, we assume that the corresponding schema document uses the default values of
elementFormDefault and
attributeFormDefault, and does not specify the
form attribute for any items it defines. Then the items in this document are in namespaces as follows:
-
-
That is the namespace given by the default namespace declaration for this element and its immediate children (
xmlns="mynamespace").
-
The
<ClassA> element does not have a namespace prefix that would indicate some other namespace.
-
-
-
-
The namespace declaration for the parent element indicates that the default namespace here is null (
xmlns="").
-
These elements do not have a namespace prefix that would indicate some other namespace.
-
The element
<String2> is the namespace
mynamespace, because that is the default namespace specified in its parent element.
In Caché XML support, you specify namespaces on a class-by-class basis. You use the
NAMESPACE class parameter to specify the namespace for instances of that class, as well as its immediate child objects. Also, you use the
ELEMENTQUALIFIED and
ATTRIBUTEQUALIFIED parameters to specify whether properties of its object-valued properties are global (and belong to the same namespace as the parent) or local.
Note:
You can also specify
ELEMENTQUALIFIED as a property parameter, if needed for unusual scenarios, not discussed in this book.
Particularly with namespaces, it is important to remember that an XML-enabled object is handled differently depending on the context. For example, if you export an
Address object at the top level, it is a global element. If you export a
Person object that includes a reference to an
Address object, then
Address is a local element (as are all other properties of
Person). Global and local elements are assigned to namespaces differently.
If you import or export an XML-enabled object at the top level, that object becomes a global element and is assigned to a namespace as follows:
-
If the
NAMESPACE parameter of the class is specified, the element is assigned to that namespace.
-
For example, consider the following class definition:
Class MyApp.Person Extends (%Persistent, %XML.Adaptor)
{
Parameter NAMESPACE = "http://www.person.org";
Property Name As %Name [ Required ];
Property DOB As %Date(FORMAT = 5, MAXVAL = "+$h") [ Required ];
}
If you export or import an object of this class, the projection might look as follows:
<Person xmlns="http://www.person.org">
<Name>Isaacs,Rob G.</Name>
<DOB>1981-01-29</DOB>
</Person>
This section describes how to specify the namespace for a property that is projected as an element.
If you import or export an XML-enabled object at the top level, any property that is projected as an element becomes a local element by default. There are two possible namespace assignments for these local elements:
-
If the
ELEMENTQUALIFIED class parameter is 1 for the parent class, the local elements are qualified, and they are explicitly included in namespace of their parent element.
-
Notice that in both cases, the namespace in the child class is ignored.
Note:
The default for
ELEMENTQUALIFIED depends on whether the input or output is in literal
format or encoded format. Literal format is the default and the most common.
You can make a property into a global element and assign it to a namespace. To do so, you set the
XMLREF property parameter to 1. The following describes how the corresponding element is assigned to a namespace:
-
If the
REFNAMESPACE property parameter is specified, the element is in that namespace.
-
Otherwise the element is assigned to a namespace as follows:
-
If the property is a type
and specifies the
XSDTYPE class parameter, the element is in the namespace of the parent class.
-
Otherwise, if the property class defines the
NAMESPACE class parameter, the element is in the namespace of the property class.
-
If the property class does not define either of these class parameters, the element is in no namespace.
This section describes how to specify the namespace for a property that is projected as an attribute. The
ATTRIBUTEQUALIFIED parameter specifies whether attributes are qualified by a namespace prefix; the possible values are as follows:
-
0 (the default), which means that no namespace prefix is included.
-
1, which means that a namespace prefix is included.
The
XMLREF and
REFNAMESPACE property parameters are also supported for properties that you project as attributes.
For a property projected as an attribute, if you set the
XMLREF property parameter to 1, the corresponding attribute is assigned to a namespace as follows:
-
If the
REFNAMESPACE property parameter is specified, the attribute is in that namespace.
-
-
If the property is a type
and specifies the
XSDTYPE class parameter, the attribute is in the namespace of the parent class.
-
Otherwise, if the property class defines the
NAMESPACE class parameter, the attribute is in the namespace of the property class.
-
If the property class does not define either of these class parameters, the attribute is in no namespace.
When you generate XML output for an object, the system generates namespace prefixes as needed. The first namespace prefix is
s01, the next is
s02, and so on. You can specify different prefixes. To do so, set the
XMLPREFIX parameter in the class definitions for the XML-enabled objects themselves. This parameter has two effects:
-
It ensures that the prefix you specify is declared in the XML output. That is, it is declared even if doing so is not necessary.
-
It uses that prefix rather than the automatically generated prefix that you would otherwise see.
For example, suppose your class definition is as follows:
Class GXML.Person Extends (%Persistent, %XML.Adaptor)
{
Parameter XMLPREFIX = "p";
Parameter NAMESPACE = "http://www.person.com";
Parameter XMLNAME = "Person";
Property Name As %Name;
}
For this class, XML output looks like the following:
<?xml version="1.0" encoding="UTF-8"?>
<Person xmlns="http://www.person.com" xmlns:p="http://www.person.com">
<Name>Umansky,Jocelyn O.</Name>
</Person>
To simplify development, debugging, and troubleshooting, InterSystems recommends the following practices:
-
If you need to specify namespaces, specify
NAMESPACE in
all your XML-enabled classes. Otherwise, the defaulting rules become complex.
-
If you need to control whether local elements are qualified, also specify the
ELEMENTQUALIFIED parameter in
all your XML-enabled classes.