How to add style to XML (original) (raw)

The CSS2 Recommendation contains a brief tutorial on using CSS with XML (see § 2.2). At the time CSS2 was written the official specification for style in XML wasn't ready. Here is what that tutorial should have contained. Note that the examples use CSS, but in most cases the style rules can also be written in XSL.

External style sheets

Tip: Try it in your browser

HTML has a link element to link to external style sheets, but not every XML-based format will have such an element. If there is no suitable element, you can still attach external style sheets by means of the xml-stylesheet processing instruction like this:

... rest of document here...

This processing instruction (PI) must come before the first tag of the document. The type="text/css" is not required, but it helps the browser: if it doesn't support CSS, it knows it won't have to download this file.

Just as with the link element of HTML, there can be multiple xml-stylesheet PIs and they can have attributes to set the type, medium and title.

Example

Here is a larger example. Let's assume we have three style sheets. The two last ones are each other's alternative, and the reader of the document may choose which one to use. Except when the document is printed, in which case we only want to use the last style. Here is the common style sheet:

/* common.css */ INSTRUMENT { display: inline } ARTICLE, HEADLINE, AUTHOR, PARA { display: block }

This is one of the alternative styles, in a file called “modern.css”:

ARTICLE { font-family: sans-serif; background: white; color: black } AUTHOR { margin: 1em; color: red } HEADLINE { text-align: right; margin-bottom: 2em } PARA { line-height: 1.5; margin-left: 15% } INSTRUMENT { color: blue }

And here is the other one, called “classic.css”:

ARTICLE { font-family: serif; background: white; color: #003 } AUTHOR { font-size: large; margin: 1em 0 } HEADLINE { font-size: x-large; margin-bottom: 1em } PARA { text-indent: 1em; text-align: justify } INSTRUMENT { font-style: italic }

The XML document with these three style sheets linked to it looks like this:

Fredrick the Great meets Bach Johann Nikolaus Forkel One evening, just as he was getting his flute ready and his musicians were assembled, an officer brought him a list of the strangers who had arrived.

For more details, see the W3C Recommendation “Associating Style Sheets with XML documents”

Embedded style sheets

Tip: Try it in your browser

HTML has a style element that allows the style sheet(s) to be embedded directly in the HTML file, without the need for an external file. In some cases that is easier, especially when the style sheet is very specific to that document.

Most XML-based formats will not have such an element, but the same PI that links to external style sheets can also be used to point to style sheets that are embedded in the document itself.As of February 2006, there are still technical problems with this and no formal specification exists. For example:

INSTRUMENT { display: inline } ARTICLE, HEADLINE, AUTHOR, PARA { display: block } EXTRAS { display: none } Fredrick the Great meets Bach ...

In this case the type="text/css" attribute must be present, otherwise the browser (or other program) has to guess the style sheet language. The xml-stylesheet PI now points not to an external style sheet, but to an element of the document itself. That element is identified by an id attribute that serves as the target of the link. (Depending on the particular XML format, the id attribute may be called something else; in some formats there may not be a suitable attribute at all.)

Unsolved problems

The W3C Recommendation “Associating Style Sheets with XML documents” doesn't define the case of embedded style sheets, although it seems a reasonable extrapolation to allow URL fragments (starting with a “#”). At this time, early 2006, there are still unsolved problems and there is no published specification. The problems are as follows:

  1. Because the embedded style sheet is not downloaded separately from the server, the server cannot tell the browser what the format of the style sheet is. Therefore, the type attribute is required in this case. It is undefined what happens if the attribute is omitted: is the style sheet ignored? is it assumed to be CSS? is there some algorithm to determine the language?
  2. In most XML-based formats, a fragment identifier identifies a complete element, not the contents of an element. But a style sheet that starts with <ARTICLE> is not correct CSS, so it seems there needs to be an extra rule that a fragment identifier used in a style sheet PI points to the contents of an element, not to the element itself.
  3. Similarly, it is undefined what happens if there are child elements inside the element that is pointed to. Does the style sheet consist of all the contents of all the elements concatenated? the contents of just the first element? or is this an error and is the whole element ignored?
  4. In the example above, the URL pointed into the document itself. The fact that the browser is able to look at that URL at all indicates that it knows how to parse XML and is probably capable of finding the indicated style element. But now consider a URL that points to a fragment of an external document. In order to succesfully retrieve the style sheet, the browser must first download and parse the external document and then extract and parse the style sheet. But the type attribute only gives the type of one of the two and thus the browser cannot know if it is able to use the style sheet. It is not even defined whether the type attributes gives the type of the external document or of the style sheet embedded in it.

Other problems

  1. The style sheet PI is most useful with “Generic XML,” i.e., with XML in a format that the browser doesn't know. Thanks to the style sheet, it will at least be able to display something. Well-known formats, such as SVG, SMIL or XHTML, have their own rules for rendering that go beyond what a style sheet can specify. But there are other things that a browser also doesn't know when the document is treated as Generic XML: in particular, it doesn't know which attributes are ID attributes. There is a W3C Recommendation for an attribute called xml:id and if the document contains attributes of that name, it is very likely that the URL fragment points to one of those. But if there are no such attributes, the browser must try other means to determine which attributes are IDs. If the document has a DOCTYPE at the top and the browser is able to retrieve the DTD that it points to, that DTD will specify the attribute. But browsers may not be able to read DTDs or there may not be a DOCTYPE.
  2. A fragment ID is only one way to point to an element in a document. Another W3C Recommendation defines XPointers to identify elements in a document without the need for ID attributes. But understanding XPointers is currently not a requirement for browsers using the style sheet PI and thus it is unclear if browser may interpret XPointers if they can or if they must ignore them.

Inline styles

HTML also allows styles to be attached directly to individual elements by means of the style attribute. Most XML-based document formats will not have such an attribute, although some may allow features (modules) from HTML to be used inside the document.

Class attributes

Tip: Try it in your browser

The class attribute that allows you to create subclasses of elements in HTML is also not likely to be available in the majority of XML-based document formats. Of course, CSS lets you select elements based on any attribute, not just class, but the syntax is less convenient.

Here is an example. If there is a class attribute and the document format defines that it works like in HTML, we can use the notation with the dot. (Therefore, this particular example won't work, because is not a format that browsers know as something that has class)

s { display: none } p { display: block } p**.note** { color: red }

Some text...

A note...

If the document format doesn't specify that class creates a subclass, then you'll have to use the longer selectors with "[ ]":

s { display: none } p { display: block } p**[class~=note]** { color: red }

Some text...

A note...

If there is no class attribute, but there is something else we can use, the attribute selectors "[ ]" still apply:

Try it in your browser

s { display: none } p { display: block } p**[warning="yes"]** { color: red }

Some text...

A note...