
Namespaces, Name With Spaces, and Attribute Values
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
- XML Schema Part 0:
Primer does indeed use the
xsd:namespace prefix. (For instance, see the sample Purchase Order Schema.) - However, that namespace prefix is nowhere to be found in the main XML Schema Part 1: Structures,
which uses
xs:everywhere. - And XML Schema Part 2:
Datatypes uses
xsd:in the examples, butxs:for its Appendix A, the normative Schema for Datatype Schemas.
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 | |
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.
2007-05-08 10:18:40 Nishant_MC- Extracting Attribute Value
2006-08-15 15:45:55 lfukazawa - How do I ignore elements or attributes in a particular namespace?
2003-10-22 13:25:09 Salvatore Mangano