Menu

Namespaces, Name With Spaces, and Attribute Values

October 8, 2003

John E. Simpson

Q: What namespace prefix should I use in a W3C Schema?

Although the W3 Schema specification uses the namespace prefix xsd:, it looks as though in current practice only xs: is used.
Could you please confirm if this is the case and is the reason just that it is shorter?

A: Actually, it depends on which part of "the W3 Schema specification" you're referring to

What's going on here? Isn't one prefix the right one?

While one might wish for more consistency in the specs to avoid this sort of confusion, in fact there's no such thing as a "correct" W3C Schema namespace prefix or even simply a better one. Indeed, there's no such thing as a correct or even better namespace prefix for any XML application at all. That's because XML processing software -- at least, software which conforms to the Namespaces in XML Recommendation -- doesn't care about the prefix; it cares only about what URI the prefix is associated with. The prefix is just a shorthand way of referring to the URI.

Assume an XML document, presumably a W3C Schema document, opens in this fashion:

<xs:schema

xmlns:xs="http://www.w3.org/2001/XMLSchema">

   ...

   <xs:element name="elem1"

type="Address">

When the processor encounters the xs:element element, it actually "understands" it in something like this form, substituting the URI for the prefix:

{http://www.w3.org/2001/XMLSchema}element

This notation -- the namespace URI enclosed in curly braces, followed by the element's local name -- is used internally almost universally by XPath-aware processors, such as XSLT engines. If you think about it, you'll see that it thus really doesn't matter what prefix you use, as long as you choose one which isn't misleading to a human reader and then use it consistently. For instance, you might rework the partial XML document (Schema) above as follows:

<W3CSchema:schema

xmlns:W3CSchema="http://www.w3.org/2001/XMLSchema">

   ...

   <W3CSchema:element name="elem1"

type="Address">

If it doesn't make any difference which prefix we use, why choose one prefix over another? I don't know, but suspect, that use of the xs: prefix might allude to a predecessor of XML Schema, known as XSchema, later renamed the Document Definition Markup Language (DDML). And, as you suggest, it does save a character for every namespace-qualified name. On the other hand, simply using x: would be even shorter, just not as clear. As for xsd:, maybe it's meant to associate the namespace with the filename extension, ".xsd", commonly used for XML Schema documents.

So, sure, go ahead, use xs: for brevity's sake, xsd: if you want to associate the namespace prefix with the Schema document's extension, or anything else. Just keep the URIs correct, and keep the namespace prefix meaningful and consistent.

Q: How do I ignore elements or attributes in a particular namespace?

What is the best approach to copy only elements and attributes in namespace "a" and ignore everything in namespace "b", using XSLT? For instance, in this document,

<a:root xmlns:a="a" xmlns:b="b" >

   <a:child name="attr1" b:foo="foo1" />

   <a:child name="attr2" b:foo="foo2" />

</a:root>

I'd like to copy the a:root and a:child elements, as well as the name attribute of each a:child, but ignore the b:foo attributes.

A: I'm not sure if this is the "best" approach -- it's not particularly elegant -- but a straightforward way to do it is simply to select only those element and attribute names that do not start with the "undesirable" namespace prefix. This requires that you use the XPath name() function, in concert with the not() and starts-with() functions. Here's a pair of xsl:template elements to do so might look something like this (substituting an XHTML result tree for the copy operation, for demonstration purposes):

<xsl:template

match="*|@*[not(starts-with(name(),

'b:'))]">

   <h3>Copying <xsl:value-of

select="name()"/>...</h3>

   <xsl:apply-templates

select="*|@*[not(starts-with(name(),

'b:'))]"/>

 </xsl:template>



 <xsl:template match="@*">

   <h4>Copying <xsl:value-of

select="name()"/>...</h4>

 </xsl:template>

Note that you can't use the local-name() function, which strips off the namespace prefixes. You also can't use the namespace-uri() function to test for the desirable namespace prefix: you won't pick up (in this case) the name attributes.

Q: Can a parameter name include a space?

I need to declare some XSLT parameter with whitespace in the name. Is this

<xsl:param name="my value" />

allowed?

A: No. Parameter names must be legitimate XML names. A simple attribute value, even that of an xsl:param element's name attribute, may contain whitespace and be perfectly well-formed as XML . But xsl:param, like xsl:element and xsl:attribute, is intended to create a unique, easily parsed instance of an object in a document. That a parameter's name, once created, is later referred to using a dollar sign -- like $my_value, say -- rather than enclosed in angle brackets is only superficially different from the name of an element or an attribute. Like any other programming language, XSLT simply does not allow spaces in the names of identifiers used by programs written in that language.

The whole point of XML is to simplify markup by eliminating as many options as possible. Nearly every XMLoid has a wish list of Things XML Might Do For My Convenience. But the XML world is complicated enough without trying to satisfy everyone. In my opinion, core XML remains a model of how to do something good enough. So you're stuck; either reevaluate your need or consider some non-XML solution.

Q: How do I build an attribute value in XSLT using a variable value?

I don't mean "variable" in the sense of an XSLT variable. I mean the actual value isn't known until runtime, taken (say) from an element's value. For instance, if I want to put this in the output:

<input style="width:some-value-in-points">...</input>

and the number of points is available as an element value elsewhere in the document, how do I substitute it in place of the "some-value-in-points"?

A: The only real trick is to know that an XSLT stylesheet can build attributes not just using literal values, but by way of a special XSLT element, xsl:attribute.

Assume you've got a source document which looks like this (ignoring whitespace added for legibility):

<root>

   ...

   <textwidth>150</textwidth>

   ...

</root>

Also assume that there's only one textwidth element in this document. In a template rule in the stylesheet, you'd include something like this:

<input>

   <xsl:attribute

name="style">width:<xsl:value-of

select="/root/textwidth"

/>pts</xsl:attribute>...

</input>

Also in XML Q&A

From English to Dutch?

Trickledown Namespaces?

From XML to SMIL

From One String to Many

Getting in Touch with XML Contacts

The xsl:attribute element must immediately follow the element you want to assign the attribute to -- the input element, in this case. It takes a name attribute, and the resulting attribute will have the indicated name. The string-value of the xsl:attribute element is assigned as the resulting attribute's value. In the above example, we've instantiated (a) an input element, which has (b) a style attribute the value of which is the concatenation of the text string "width:", the string-value (150) of the source document's textwidth element, and the text string "pts". Thus:

<input

style="width:150pts">...</input>

By the way, note that you needn't get the value to be substituted from the source tree. You can get it from another document altogether, using the document() function. And this other document can even be the stylesheet itself, if that's what you're after: just supply an empty string as the argument to the function:

document("")

For one demonstration of this, see the XSL FAQ, in the example provided by Ken Holman.