Parameterizing Namespaces

Parameterizing Namespaces

One of the biggest benefits of parameterization is that it lets you vary the namespace prefix. The fundamental principle of namespaces is that the prefix doesn't matter, only the URI matters. For instance, Statement , mb:Statement , and bank:Statement are all the same just as long as Statement is in the default namespace and mb:Statement and bank:Statement are in contexts where the mb and bank prefixes are mapped to the URI. Only the local name and URI matter. The prefix (or lack thereof) doesn't.

However, DTDs violate this principle. In a DTD only the qualified name matters. The parser validates against the prefix and local name. It ignores the namespace URI. You cannot change the prefix without changing the DTD to match. However, parameterization provides a way out of this trap. First, define the prefix and the colon as separate parameter entity references.

 <!ENTITY % statement.prefix "stmt"> <!ENTITY % statement.colon  ":"> 

Next, define the names using these parameter entities.

 <!ENTITY % Date.qname "%statement.prefix;%statement.colon;Date"> <!ENTITY % Transaction.qname              "%statement.prefix;%statement.colon;Transaction"> <!ENTITY % Amount.qname              "%statement.prefix;%statement.colon;Amount"> <!ENTITY % Account.qname              "%statement.prefix;%statement.colon;Account"> <!ENTITY % TransactionContent              "%Account.qname;?, %Date.qname;, %Amount.qname;"> 

You'll normally also want to parameterize the namespace declaration using either an xmlns or xmlns:prefix attribute, typically on the root element. For example:

 <!ENTITY % NamespaceDeclaration              "xmlns%statement.colon;%statement.prefix;"> <!ATTLIST %statement.prefix;%statement.colon;;   %NamespaceDeclaration; CDATA   #FIXED ""> 

To adjust the prefix used in a particular instance document just override statement.prefix and statement.colon in the internal DTD subset to match what appears in the instance document. For example, the following code sets the prefix to bank .

 <!DOCTYPE Statement PUBLIC "-//MegaBank//DTD Statement//EN"                            "modular_statement.dtd" [   <!ENTITY % statement.prefix "bank">   <!ENTITY % statement.colon  ":"> ]> 

To use the default namespace set both statement.prefix and statement.colon to the empty string.

 <!DOCTYPE Statement PUBLIC "-//MegaBank//DTD Statement//EN"                            "modular_statement.dtd" [   <!ENTITY % statement.prefix "">   <!ENTITY % statement.colon  ""> ]> 


When parameterizing namespace prefixes like this, it is essential that you do not skip any steps. In particular, you must use the double indirection of defining entity references for both the element's qualified name and for its local name and prefix. Do not try something like this:

 <!ELEMENT %statement.prefix;%statement.colon;Number                                           (%Number.content;)> 

For various technical reasons, this will fail. In brief, without the double indirection the parser adds extra space around the resolved entities so that the resolved declaration is malformed .

Effective XML. 50 Specific Ways to Improve Your XML
Effective XML: 50 Specific Ways to Improve Your XML
ISBN: 0321150406
EAN: 2147483647
Year: 2002
Pages: 144 © 2008-2017.
If you may any questions please contact us: