Chapter 9 Image

STYLING XML WITH CSS

Throughout this book, we've explored both markup and CSS and how to develop patterns to leverage one from the other. We also discussed the various forms that your projects might take, such as traditional on-screen display, print, and mobile media. However, in all this time we've not yet explored the versatility and extensibility that we alluded to as being possible with XML in the beginning of this book.

In this chapter, you'll break free of styling HTML and spread your wings to include other forms of content, such as Atom feeds, SVG images, and your own custom XML applications. You'll see that many mainstream browsers support non-HTML-based web content very nicely, and you'll learn how to deal with some of the remaining browser quirks that styling client-side XML produces.

Using XML for your markup

HTML and XHTML are commonly used throughout the Web for marking up web pages. XML is not nearly as common for this use, but the good news is that it is for the most part supported by all major modern browsers. If you wish to dabble in XML or rebel against the HTML establishment, you can go right ahead.

CSS can be used to style much more than HTML or XHTML. If you are willing to adhere to the stricter rules of XML and aren't afraid of defining your own markup, XML may be a viable alternative for marking up your site. Or you may have reasons for styling existing XML sources: a data report in XML format, an SVG image, or an existing RSS feed are all candidates for XML sources that might be improved with a little CSS. Using CSS with XML can be liberating compared to dealing with HTML's constraints, but there are pros and cons with either approach.

Problems with POSH

Plain Old Semantic HTML (POSH) is a wonderful construct for the Web. It has proven time and time again to be a simple and effective format for delivering vast quantities of information over the Internet in a lightweight and easy-to-understand format. But there are some shortcomings. For one, HTML only tells us the format of a document—it does not tell us much about the content itself. Another problem is the legacy baggage that comes with HTML—all those browser bugs, and those varying opinions as to how elements are handled.

XHTML was intended to be a reformulation of HTML into XML, a path forward to advance the capability of web authors by providing the tools and extensibility of XML in an HTML framework. It was a great idea in theory—if only browsers would have played along.

Freedom from HTML

Casting aside the shackles of HTML can be liberating. Styling XML will free you from the default browser styles and implied meanings that come with HTML. You can make your own rules—define your own set of tags and attributes that more closely match the need in question. And then if you do choose XML, you have the full power of the Turing-complete XSL suite of technologies at your disposal too.

In HTML, web browsers treat certain elements in certain ways in all cases, and there's little you can do to get around that. For one, the <body> element is going to be the part of the document that appears in the viewport. Everything else going into the viewport is going to be a child of the <body> element. On the other hand, none of what is placed in the <head> section of your HTML can be styled. (Not that you'd likely need to—but say you wanted to extract attributes from meta elements using attr() and have them show up somewhere?) Nor can the overall <html> element be styled (except for specifying the behavior of its children that might appear at <body> and below).

Oh yeah? Well, XML sucks!

That isn't to say XML is without its own failings. Sometimes being too perfect is a burden in and of itself.

XML documents optionally begin with an XML prolog. The prolog may consist of two parts: the XML declaration and the document type definition (DTD). The DTD is very common in HTML and XHTML contexts. But with the XML declaration, it's not so common. It is this declaration that causes Internet Explorer 6 to trip and use quirksmode instead of standards mode rendering. The XML declaration looks like this:

<?xml version="1.0"?>

In conjunction with a DTD it might look like this:

<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

Another IE6 bug is the fact that web servers are supposed to serve XHTML using a special MIME type—specifically, application/xhtml+xml. If a page is served using this MIME type, IE will try to download the page as a text file instead of rendering it. For this reason, XHTML is often simply served as text/html. This works great for user agents that don't yet support the MIME type. But serving pages as text/html limits the benefit of having all this great XML at our fingertips. Browsers will continue to treat your well-formed and validating XHTML as plain-old HTML. It is nice-looking HTML, but it's not being honored with the full power of the XML juggernaut. In other words, XSL isn't going to work. No XPath for you. (On the plus side, IE will not throw up its arms and give up when one tiny mistake in your markup creeps through.)

According to the spec (http://www.w3.org/TR/xhtml-media-types/#media-types), you're supposed to serve XHTML as XML to those browsers that declare their support for it and as text to those that don't. So although the W3C also says that the text/html MIME type isn't suitable for XHTML, they don't explicitly forbid its usage, due to legacy user agents. As of this writing, XHTML 1.1 is the only version of XHTML that the W3C insists should be served as XML.

Another problem: XML is supposed to be fussy, but most browsers are far more forgiving than XML allows and let XHTML get away with crimes against XML by rendering pages that should have failed. This harkens back to the wild and wooly days of the early Web, when rules were few and it was still a free-for-all. Standards are a double-edged sword; they were created to end the problems associated with ensuring sites were functional in the popular browsers, but fussy XML parsing means a browser should fail to render a page if the XML is not valid. One of the things that let HTML flourish so fast and wide was the fact that it was forgiving: HTML authors could make mistakes and it wasn't the end of the world. Their pages would still work. Imagine if XML was the norm and the world tried to adopt it back in those early days—we'd have a much more pristine, and much smaller World Wide Web than we have today. Take that for what you will.

Search engines for the most part have been trained to pay particular attention to the structures and conventions of HTML semantics. With XML, you are potentially casting aside all this good Google-juice in favor of your ideals. That is not to say that XML won't get indexed, but certain tags such as <h1> and <title> have particular meaning when search engines are indexing your site.

Double the style sheet fun

There are not one but two types of style sheets in XML. We have our familiar and traditional CSS, which is going to work mostly the same as you would expect it to work in an XHTML context, and then we have the Extensible Style Sheet Language (XSL), which gives web authors a great deal of power in how XML documents are interpreted.

XSL is actually a suite of technologies, which includes Extensible Style Sheet Language Transformations (XSLT), XPath, and XSL Formatting Objects (XSL-FO). The XSL-FO component is sometimes itself referred to as XSL, but for the purposes of this book let's keep things separate for clarity: XSL will be used for the general context, and XSL-FO will be used for the specific component it refers to.

CSS vs. XSL

So which to use—CSS or XSL? That all depends on the complexity of what you want to accomplish. For most cases, CSS will probably be fine, and is going to be the likely candidate for styling your project. If you need to do significant filtering or rearranging of your XML, then XSL might be the way to go. Heck, you can probably justify using both in many contexts—transforming an XML document into the correct format before applying a little CSS might be just what the doctor ordered.

In choosing between CSS and XSL, consider the Rule of Least Power. This rule states that when designing computer systems, you are often faced with a choice between using a more or less powerful language for publishing information, for expressing constraints, or for solving some problem. This finding explores trade-offs involving the choice of language to reusability of information. The Rule of Least Power suggests choosing the least powerful language suitable for a given purpose.

Styling a simple XML file

Custom XML applications may appear in all sorts of contexts. Perhaps you've exported a load of data from some application and want to make it more readable through a style sheet. Or perhaps you've created your own markup scheme and are putting it to use for a web project. In any case, the rules for CSS in XML are largely similar to the HTML world, but with a few minor caveats, which we'll explain as we go through the remainder of this chapter.

Linking a style sheet

Linking style sheets to XML documents should look very familiar to you. This operation is largely the same whether you're linking a CSS style sheet or an XSL style sheet.

<?xml-style sheet type="text/css" href="xmlstyles.css"?>

The difference here is that the opening bracket must begin with <?xml-style sheet and the element must close with a ?>. The rest of it is similar to what you will find in HTML.

Embedding a style sheet

Currently there is no generic mechanism for embedding CSS in XML documents; a <style type="text/css"> has to be defined in the given application's DTD or schema. XHTML and SVG are examples of XML applications that do have provisions for embedding CSS in a <style> element.

There is a small difference in how you embed CSS between HTML and XML documents that you must be aware of: you must escape the contents of a style sheet element—the CSS rules—as unparsed character data (CDATA). The reason for this is so that any < and & characters that might be used in the style sheets are not interpreted as markup.

<style type="text/css"><![CDATA[
    giraffe {
        color: #FC6;
        background-image: url(giraffe_pattern.tif);
        border: none;
    }
]]></style>

The thing to remember about embedding CSS in an XML document is that you have to be sure that the <style> element is supported. Without support for <style> already defined, the style sheet content will not make sense.

Using external style sheets is the preferred method for applying style to XML. If your style sheet will contain the characters <, &, ]]>, or --, you will definitely want to use an external style sheet, and embedded style sheets in XML still lack formal specification. Use the xml-style linking method whenever possible.

Putting the X back in eXtensible

Consider XHTML for a moment. The first word in that acronym is “extensible.” What does that mean? You know XHTML like the back of your hand I bet, but have you ever extended it? How do you go about extending this markup language?

It is important to remember that XHTML is, by definition, an application of XML itself, and despite the problems mentioned earlier there is a good argument for allowing XHTML to be processed as an XML document. Even if it is being interpreted as text/html, a lot of this stuff will still work from a CSS/display standpoint. You are not limited to those tired old <h1>s and <p> tags. Try a little <dc:title> (a Dublin Core title element) or <ml:mo> (a MathML mathematical operator) on for size and see how it fits into your XHTML document.

Extending XHTML through namespaces

XHTML is an application of XML, and is defined as such through its namespace and a DTD. In practice, the namespace is usually implied, but technically you should really define the namespace like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>An XHTML 1.1 Document</title>
    </head>
    <body>
        <h1>XHTML is keen</h1>
        <p>This is an example of XHTML 1.1.</p>
    </body>
</html>

The namespace here is defined without a prefix. This means all of the elements in this document are going to appear as you would expect to see them in a standard HTML document. No surprises here. But how would it look if we added a second namespace? There can be only one default namespace, so any other namespaces added to our document are going to require prefixes:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" Image
xmlns:vla="http://natasha.example.com/ns/viola">
    <head>
        <title>XHTML + Viola</title>
    </head>
    <body>
        <h1>XHTML is keen</h1>
        <p>This is an example of XHTML 1.1, now with more viola.</p>
        <vla:viola>
        <vla:maker>Amati</vla:maker>
            <vla:year>1566</vla:year>
            <vla:value>$940,000</vla:value>
        </vla:viola>
    </body>
</html>

We now have a hybrid piece of markup, with the default namespace being XHTML and the namespace prefixed with vla pointing to some custom XML definition based on violas.

Namespaces may be easily and arbitrarily added to XML documents, including XHTML. Each will require a unique prefix (with one being allowed no prefix as “the default namespace”), and the url property should have a unique URL placed in quotes. The URL itself is arbitrary—it can be any URL as long as it is treated as unique for the given document.

Styling namespaces

Styling XML namespaces is a bit different than what you would probably expect. Your intuition likely is telling you that simply writing the selector as it appears as a namespace would be good enough:

dc:title { color:blue; }

What do you think might be wrong with that rule? If you guessed that the colon character separating dc and title is the culprit, you'd be on the right track. Colons in selectors are for indicating pseudo-selectors. There is no :title pseudo-selector, nor is that what we want to imply here. Something else needs to be done.

To handle namespaces in CSS, you must first declare a namespace in your style sheet, and then you need to write selectors using the pipe character (|) to separate namespaces and selectors. Namespaces are declared using @namespace:

@namespace dc url Image
(http://dublincore.org/documents/2007/07/02/dcmi-namespace/);

In this example, dc is the prefix that will be used throughout your style sheet for any rules using the namespace. The URL serves as a unique identifier—it can be any URL, although some organizations (such as the W3C or Dublin Core) recommend specific URLs. If you're defining a custom DTD, you might post that somewhere and use it as your URL choice. The important thing is that this URL be unique for the style sheet in question. All @namespace rules must come after any @import and @charset rules, and before the rest of the rules in the style sheet in which they appear. This is important—if the order is incorrect, your browsers may ignore the namespace rule and your styles won't work as expected.

Now that this preliminary business is taken care of, it is time to create a CSS rule. A rule for our <dc:title> element would look something like this:

dc|title { color:blue; }

The pipe character serves to separate the namespace prefix from the element in CSS. The rest of the rule may proceed as expected.

Styling namespaces in Internet Explorer

What would a killer web standards technique be without a corresponding IE failure? Rest assured, styling XML namespaces is no different.

Early on in the life of the XML specification, namespaces had yet to have a CSS construct defined that would handle them. Failing solid guidance in the specification and anxious to get things moving, Microsoft implemented namespaces in style sheets using the backslash character to escape the colon:

dc:title { color:blue; }

With this pattern, you won't need to declare a @namespace for the IE set. In fact, @namespace isn't even supported in any version of Internet Explorer, and that includes IE8. Plan on using conditional comments to link to a dedicated style sheet for any IE-specific code:

<!--[if IE]>
<?xml-stylesheet type="text/css" href="msie.css"?>
<![endif]-->

To achieve the widest level of compatibility with current browsers when styling XML with namespaces, as well as to future-proof your work, you should first set your styles using the standards-based @namespace and prefix|element{} pattern. Then add your IE-specific styles using the conditional comment pattern as indicated earlier. As of this writing, @namespace support is still not planned for any future updates to IE8, but if IE9 rolls around with support for the correct implementation as defined in the specification, then your style sheets should continue to work.

Painting SVGs

Scalable vector graphics (SVG) is an open and standards-based way of describing two-dimensional images in XML. As of this writing, SVG 1.1 (http://www.w3.org/TR/SVG11/) and SVG Tiny 1.2 (targeted at mobile devices; http://www.w3.org/TR/SVGTiny12/) are the current W3C recommendations. Since SVG is simply a non–binary-text-based file format written in XML, it is possible to create and edit images manually using nothing but a text editor, and it is easy to generate and manipulate images programmatically using server-side programming languages like PHP or Ruby, or using desktop software programs such as Adobe Illustrator or Inkscape.

An interesting feature of SVG that sets it apart from several other file formats is the fact that it supports text and is itself a text-based format. This gives SVG the capability of providing easily searchable information baked right into the file format in a way that search engines are already fundamentally capable of and good at. Couple SVG with the idea of combining XML applications in one document (such as, say, an XHTML document) and you have an interesting opportunity for a more semantic and meaningful Web.

Realistically it may not be terribly practical to hand-code finely detailed SVG images. But since SVG is just XML for the most part, it is highly conducive to programmatic manipulation and even modification by hand through its styling constructs. For example, if you wanted to modify a map of the United States to highlight the state of California, it would be easy for you to open the file in a text editor; find, say, the #california ID that the original developer used to define the state; and give the state a nice golden background color with a blue border with a bit of style property modification. Another example would be in producing statistical graphics generated from server-side code—you could generate rich and meaningful statistical charts from real-time data simply by programmatically modifying the variables in the SVG file.

SVG supports the styling of its markup using CSS. While SVG itself is a purely presentational language with its own constructs built in for drawing and manipulating graphics, CSS may be used with it as a styling mechanism, which opens the door for a number of interesting applications. Consider the fact that there is a vector-based image format that you can color and manipulate using a language you already know: CSS. Does that sound like something fun to play with? You betcha!

For this example, let's look at something simple—a three-bar flag. It is commonly used throughout the world as perhaps the most widely used layout for a national flag, and it is easy to write in SVG. For our XML, use the following:

<?xml version="1.0" standalone="no"?>
<?xml-stylesheet href="svgexample.css" type="text/css"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" Image
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" Image
width="900" height="600">
    <rect id="bar1" width="900" height="600"/>
    <rect id="bar2" width="600" height="600"/>
    <rect id="bar3" width="300" height="600"/>
</svg>

And for the flag design, let's use Ireland as the example:

#bar1 {
    fill:orange;
}
#bar2 {
    fill:white;
}
#bar3 {
    fill:green;
}

The result of this simple example is a nice approximation of the flag of the Emerald Isle. With a few changes, we can move a little farther south toward the mainland and try for France:

#bar1 {
    fill:red;
}
#bar2 {
    fill:white;
}
#bar3 {
    fill:blue;
}

Vive la differénce! With a couple of switches, we can make our flag French, Irish, Italian, or whatever other country uses this layout by simply swapping out a few color values. You could even provide for a more versatile example by using descendant selectors. With the following example, Ireland and France are handled gracefully and all you would need to do is swap out the value of the ID in the parent element:

<?xml version="1.0" standalone="no"?>
<?xml-stylesheet href="svgexample.css" type="text/css"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" Image
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" Image
width="900" height="600" id="ireland">
    <rect id="bar1" width="900" height="600"/>
    <rect id="bar2" width="600" height="600"/>
    <rect id="bar3" width="300" height="600"/>
</svg>

And the CSS for our Irish flag would be

#france #bar1 {
    fill:red;
}
#ireland #bar1 {
    fill:orange;
}
#bar2 {
    fill:white;
}
#france #bar3 {
    fill:blue;
}
#ireland #bar3 {
    fill:green;
}

Just change the id value in your XML from ireland to france and back as needed. See if you can add styles for Italy to your style sheet! Hint: #bar1 would be green, and #bar3 would be red.

The SVG specification does include a definition for a <style> element. So if you needed to have a self-contained single file for your image, you could do so. In this case, the previous example would look like this:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" Image
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" Image
width="900" height="600" id="ireland">
    <style type="text/css"><![CDATA[
    #france #bar1 {
        fill:red;
    }
    #ireland #bar1 {
        fill:orange;
    }
    #bar2 {
        fill:white;
    }
    #france #bar3 {
        fill:blue;
    }
    #ireland #bar3 {
        fill:green;
    }
    ]]></style>
    <rect id="bar1" width="900" height="600"/>
    <rect id="bar2" width="600" height="600"/>
    <rect id="bar3" width="300" height="600"/>
</svg>

With this code, the image may be treated as a single file. This will be important if you want your SVGs to be easily ported or referenced as other image file formats can be, such as JPEG or PNG. For this reason, unlike most other styled markup, it is likely that most SVG files you encounter will probably be styled with embedded instead of external style sheets.

SVG and CSS2

Many of the SVG styles are unique to its specification. However, a subset of the CSS2 spec is available in SVG, which includes the following properties and at-rules:

  • clip
  • color
  • cursor
  • direction
  • display
  • font
  • font-family
  • font-size
  • font-size-adjust
  • font-stretch
  • font-style
  • font-variant
  • font-weight
  • letter-spacing
  • overflow
  • text-align
  • text-decoration
  • unicode-bidi
  • vertical-align
  • visibility
  • word-spacing
  • @charset
  • @font-face
  • @import
  • @media

The color property as applied in CSS requires some special consideration. We will discuss how color works as part of the SVG-specific styling properties in the next section. The clip and overflow properties are only applied to the outermost <svg> element. Child elements of the <svg> element will ignore any clip or overflow property values. As you might notice from the preceding list, the majority of the CSS properties here are typography related, as are many of the other things you might expect to be available in CSS such as margin, padding, background-color, and border properties. In SVG, you need other constructs to style those elements, but fortunately things will look largely similar to what you're used to in the CSS world.

SVG-specific style

Since the CSS specification itself is inadequate to handle the complexities and specific requirements of styling images, SVG includes a number of style extensions. We have already seen some use of the fill property in our earlier examples.

SVG style property/value pairs may be presented directly within the content of the markup as attributes. At the same time, SVG style properties may be treated as part of style sheets in the same way CSS works.

Here are some more property options to help you code your next work of art, along with a brief description of the intent of each property's function:

  • alignment-baseline: A text property that specifies alignment with respect to its parent element.
  • baseline-shift: Repositions the baseline of text relative to its parent element, usually resulting in a subscript or superscript effect.
  • clip-path: Points a URI to another SVG graphic to be used as a clipping path. This can be an ID reference (such as #someClippingPath) if the SVG is embedded within the same document.
  • clip-rule: Takes one of three values: inherit, evenodd, or nonzero (default). Without getting too deep into the details, imagine two concentric circles, with a clip-rule applied to the outermost circle. With nonzero, both circles would be filled. With evenodd, the inner circle would not be filled, resulting in an annulus.
  • color-interpolation: Specifies which color space interpolation should occur in, with auto, sRGB (default), and linearRGB as possible values.
  • color-interpolation-filters: Similar to color-interpolation but applied to filter effects.
  • color-profile: Defines a color profile description. Can be used like an at-rule (@color-profile) or as a property.
  • color-rendering: Tells the user agent to optimize speed or quality using the optimizeSpeed or optimizeQuality property.
  • dominant-baseline: In typography, used to determine the baseline of the script with the dominant run. Values could be alphabetic for Western contexts, mathematical for math formulas, and ideographic for the East Asian scripts Chinese, Japanese, Korean, and Vietnamese ChũImage Nôm.
  • enable-background: Describes how backgrounds are accumulated, using the property new or accumulate, or an x/y offset value.
  • fill: Paints the interior of a given element.
  • fill-opacity: Sets the opacity of the fill color.
  • fill-rule: Similar to clip-rule, using evenodd or nonzero (default) to set the fill behavior.
  • filter: Can set a URL to point to a filter that would be applied to an object.
  • flood-color: Indicates a color value to use to flood a filter subregion.
  • flood-opacity: Sets an opacity value to flood a filter subregion.
  • glyph-orientation-horizontal: Controls glyph orientation when the inline-progression-direction (set by writing-mode) is vertical relative to the reference orientation.
  • glyph-orientation-vertical: Controls glyph orientation when the inline-progression-direction (set by writing-mode) is horizontal relative to the reference orientation.
  • image-rendering: Tells the user agent to optimize speed or quality using the optimizeSpeed or optimizeQuality property. (See color-rendering.)
  • kerning: Adjusts length between glyphs.
  • lighting-color: Defines a color for light sources that can be applied against SVG's <feDiffuseLighting> and <feSpecularLighting> elements.
  • marker: Shorthand property for marker-end, marker-start, and marker-mid.
  • marker-end: Defines a marker or an arrow at the end of a path.
  • marker-mid: Defines markers at all vertices except for the beginning and end markers.
  • marker-start: Defines a marker or an arrow at the beginning of a path.
  • mask: References a <mask> element to implement a path used for generating a mask effect.
  • opacity: Sets the opacity of an object, using decimal values from 0 (fully transparent) to 1 (fully opaque). A value of 0.5 would be 50 percent opacity.
  • pointer-events: Controls under what circumstances an object can become the target of pointer events.
  • shape-rendering: Tells the user agent to optimize speed or quality using the optimizeSpeed or crispEdges property.
  • stop-color: Sets a color to use at a gradient stop.
  • stop-opacity: Sets an opacity used at a gradient stop.
  • stroke: Describes the stroke effect applied to an object.
  • stroke-dasharray: Sets pattern of dashes and gaps in a stroke.
  • stroke-dashoffset: Sets how far into a stroke the dash pattern will begin.
  • stroke-linecap: Sets the shape used at the end of open subpaths, using the values butt, round, and square.
  • stroke-linejoin: Sets the shape of corners, using the values miter, round, and bevel.
  • stroke-miterlimit: Sets a limit on the ratio of the miter length to stroke-width.
  • stroke-opacity: Sets the opacity of the stroke.
  • stroke-width: Sets the width of a stroke.
  • text-anchor: Aligns text to a specified point, using the values start, middle, and end.
  • text-rendering: Tells the user agent to optimize speed or quality using the optimizeSpeed or optimizeLegibility property.
  • writing-mode: Determines which direction text flows; left to right, right to left, and/or top to bottom.

Browser support for SVG

SVG enjoys at least partial native support in modern versions of Gecko-based browsers such as Firefox, WebKit-based browsers such as Safari, and the Opera line of browsers since version 8. As you probably guessed, there are no versions of Microsoft Internet Explorer, including version 8, that support SVG.

Fortunately for the IE users, there are excellent plug-ins that provide support for SVG. The Adobe SVG plug-in was under active development up until January 1, 2009, when active development was discontinued. The Adobe plug-in is still available for download from the Adobe web site. However, their motivations for discontinuing support included the fact that better options existed in the marketplace and that most browser vendors (save for the one big one) already feature native support for SVG. For IE users and developers who would like to recommend a plug-in, we suggest the excellent RENESIS Player, available from examotion at http://www.examotion.com/.

Making an Atom feed more presentable

The Atom Syndication Format is an XML application created to standardize web feeds, and is an alternative to RSS (although the two are largely similar). It is a proposed standard published under the Internet Engineering Task Force (IETF) as RFC 4287. RSS and Atom feeds are highly popular features of the modern Web, providing an XML-formatted feed of regularly updated content that may be subscribed to by feed reader software or consumed by software applications. Here is an example of what an Atom feed might look like:

<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Viola Universe</title>
    <subtitle>More viola than you can shake a baton at.</subtitle>
    <link href="http://viola.example.org/feed/" rel="self"/>
    <link href="http://viola.example.org/"/>
    <updated>2009-02-28T17:31:05Z</updated>
    <author>
        <name>Violaman</name>
        <email>[email protected]</email>
    </author>
    <id>http://viola.example.org/feed/iri/</id>
    <entry>
        <title>Violas Run Amok</title>
        <link href="http://viola.example.org/2009/02/28/violasrunamok/"/>
        <id>http://viola.example.org/2009/02/28/violasrunamok/id</id>
        <updated>2009-02-28T17:31:05Z</updated>
        <summary>In which the entire viola section loses all pretense Image
of control.</summary>
    </entry>
</feed>

An integrated example

Let's look at a step-by-step examination of a single XML document founded on some custom markup. For our example, we'll use an XML document that describes a list of classical music composers, including information about the composer's dates of birth and death, what period they are categorized with (such as Baroque, Classical, Romantic), and some representative works. We'll use this markup to apply some CSS styles to make it more interesting and readable. The code here is truncated due to space constraints, but the full example may be found in the chapter 9 folder of the source code downloads. Here's the code we'll start with:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE composers SYSTEM "composers.dtd">
<composers>
    <composer>
        <name>
            <givenname>Gustav</givenname>
            <surname>Mahler</surname>
        </name>
        <yearbirth>1860</yearbirth>
        <yeardeath>1911</yeardeath>
        <period>Post-Romantic</period>
        <favoriteworks>
            <work>
                <title>Symphony No.2</title>
                <date>1894</date>
                <instrumentation>Full orchestra</instrumentation>
            </work>
            <work>
                <title>Symphony No.6</title>
                <date>1906</date>
                <instrumentation>Full orchestra</instrumentation>
            </work>
        </favoriteworks>
    </composer>
    /* Code truncated here. See 09.2.1.composers.xml */
    <composer>
        <name>
            <givenname>Antonín</givenname>
            <surname>Dvo ák</surname>
        </name>
        <yearbirth>1841</yearbirth>
        <yeardeath>1904</yeardeath>
        <period>Romantic</period>
        <favoriteworks>
            <work>
                <title>Quintet</title>
                <date>1875</date>
                <instrumentation>2vl, vla, vc, db</instrumentation>
            </work>
            <work>
                <title>Symphony No. 9, in E Minor "From the New World" Image
(Op. 95)</title>
                <date>1893</date>
                <instrumentation>Full orchestra</instrumentation>
            </work>
        </favoriteworks>
    </composer>
    <composer>
        <name>
            <givenname>Charles</givenname>
            <surname>Wuorinen</surname>
        </name>
        <yearbirth>1938</yearbirth>
        <period>Modern</period>
        <favoriteworks>
            <work>
                <title>Spinoff</title>
                <instrumentation>violin, bass, congas</instrumentation>
            </work>
        </favoriteworks>
    </composer>
</composers>

The raw and unstyled XML appears as a document tree in many user agents, such as Gecko-based browsers like Camino, as shown in Figure 9-1.

Image

Figure 9-1. Unstyled XML displayed as a document tree

Try viewing this in a few browsers to get a feel for what raw, unstyled XML looks like. Firefox and Internet Explorer will render the previous code as a document tree, while Safari and Opera will render a clump of unformatted, inline text. Now let's add a style sheet. Create a file called composers.css in the same directory as the previous XML file. Insert the following line on line 2 of the XML file:

<?xml-stylesheet type="text/css" href="composers.css" ?>

Now check your browsers again; what do you see? All browsers should now be rendering that amorphous clump of text we saw earlier in Safari and Opera. Nothing really special has happened here, but you will note something of at least minor importance: all of our elements appear exactly the same. There is no variance in font sizing. There are no block elements—only inline. It is simply a shapeless stew of content.

The first step is to add some definition. Let's start by taking at the natural organization of our XML file. There are some high-level nodes in this file called <composer>, and they group the information for each composer that we have listed. This grouping is in fact defined and enforced by the referenced DTD file that is included. So the first thing we could do is to make that a block-level element in composers.css:

composer {
    display:block;
}

This sets each composer block to be rendered on its own line in the browser, as shown in Figure 9-2.

Image

Figure 9-2. Displaying the <composer> element as blocks

Instantly our example makes more sense. Each composer begins on its own new line. However, with the wrapping that likely is occurring in your browser, it still might be a little confusing. Let's add some margin and borders too:

composer {
    display:block;
    margin-bottom:1em;
    border-bottom:1px dotted #ccc;
}

These changes are reflected in Figure 9-3.

Image

Figure 9-3. Adding a little visual separation to the block elements

Now things are becoming clearer. Let's further equalize the display of our information with a bit of work on the overall layout by establishing some margins and contrast on the viewport:

composers {
    background-color:#4C4C4C;
    padding-top:4em;
    font-family:Georgia, serif;
    font-size:0.95em;
}
composer {
    display:block;
    margin:0 auto 1em auto;
    padding:1em;
    background-color:#fff;
    width:50%;
    border-bottom:1px dotted #ccc;
}

These changes will provide some contrast and immediate visual layout benefits, as shown in Figure 9-4.

Image

Figure 9-4. Establishing margins and contrast in the viewport

Now we've put our layout into clear and digestible bits of information. The outermost XML element <composers> works like our <body> and <html> elements in traditional HTML contexts, giving us a hook from which to apply global styles. Since the outermost element can set certain global properties in CSS that will be inherited, adding a font-family and font-size here makes sense. It is interesting to note here for a moment the difference between HTML and XML with respect to the <body> element. It is the <body> element that is visible to the viewport, and anything contained in the <head> is invisible. With stock XML formats, the outermost element is the default content for the viewport and hiding anything from it must be done manually.

Now that the large blocks of information make sense, we need to sort out the details of each composer in our list. Let's add a few more block-level elements and some typography to style things to be more organized:

composers {
    background-color:#4C4C4C;
    padding-top:4em;
    font-family:Georgia, serif;
    font-size:0.95em;
}
composer {
    display:block;
    margin:0 auto 1em auto;
    padding:1em;
    background-color:#fff;
    width:50%;
    border-bottom:1px dotted #ccc;
}
name {
    display:block;
    font-weight:bold;
}
work {
    display: list-item;
    list-style-type: square;
    margin-left:2em;
}
period {
    display:block;
    font-style:italic;
}

With just a few typographic changes, the content becomes instantly clearer on the page, as shown in Figure 9-5.

Image

Figure 9-5. More block treatment of the content and addition of list styles

At this point, our information is displayed fairly well considering the meaning of the markup. We first added block-level treatment to the <name> and <period> elements, and set the <work> element to display as a list-item. How often do you get to do that? In XML, it is often that you will have list-like child elements, and using the list-item value for the display property becomes entirely appropriate for this need. If you want to see something interesting, try changing the list-style-type property value to decimal instead of list-item, and then reload your page in Safari or Opera. You now have ordered lists! This is a handy tool to have around when styling long chunks of XML data, but unfortunately your mileage may vary when it comes to browser support.

Now what would really help is some indication of what some of the data types are. First, the numbers that appear directly below the names are the birth and death dates for each composer. But these are formatted poorly at best, and for someone unfamiliar with music history this might be completely meaningless. Let's see what we can do with generated content:

composers {
    background-color:#4C4C4C;
    padding-top:4em;
      font-family:Georgia, serif;
    font-size:0.95em;
}
composer {
    display:block;
    margin:0 auto 1em auto;
    padding:1em;
    background-color:#fff;
    width:50%;
    border-bottom:1px dotted #ccc;
}
name {
    display:block;
    font-weight:bold;
}
work {
    display: list-item;
    list-style-type: decimal;
    margin-left:2em;
}
period {
    display:block;
    font-style:italic;
    margin-bottom:0.5em;
}
yearbirth:before {
    content: "b. ";
}
yeardeath:before {
    content: "- d.";
}
favoriteworks:before {
    content: "Favorite works";
    font-weight:bold;
}

We now have content that is more properly labeled and readable, as you can see in Figure 9-6.

Image

Figure 9-6. Using generated content to make the data more readable

Now we've used the :before pseudo-class and the content property to generate some meaningful labels to some of our markup. The dates are now labeled a bit better, with b. appearing before the birth year and - d. appearing if and when a year of death is indicated, directly preceding this date. We added a label of Favorite Works before the list of pieces. And finally, we wrap things up with a bit of margin on the bottom of the <period> element to create a little more visual distinction on the page. The rest is detail and polish at this point.

Really what this thing needs is some images to liven up the page and associate more of a visual identity with each composer. There is no equivalent to the <img> element in our XML document, but that's OK—we won't need it. We can use background images attached to the <composer> elements by leveraging their unique id properties:

composer {
    display:block;
    margin:0 auto 1em auto;
    padding:1em;
    padding-right:150px;
    background-color:#fff;
    width:40%;
    border-bottom:1px dotted #ccc;
    background-position:96% 1em;
    background-repeat:no-repeat;
}

composer[id="mahler"] { background-image: url(img/mahler.jpg); }
composer[id="bach"] { background-image: url(img/bach.jpg); }
composer[id="shostakovich"] { background-image: Image
url(img/shostakovich.jpg); }
composer[id="beethoven"] { background-image: url(img/beethoven.jpg); }
composer[id="schubert"] { background-image: url(img/schubert.jpg); }
composer[id="stravinsky"] { background-image: Image
url(img/stravinsky.jpg); }
composer[id="dvorak"] { background-image: url(img/dvorak.jpg); }
composer[id="wuorinen"] { background-image: url(img/wuorinen.jpg); }

As Figure 9-7 illustrates, pictures really help the display of our page and give it a more personal character.

Image

Figure 9-7. Adding portraits of our composers

It's looking good! We reduced the overall width to 40% since the extra padding was pushing our layout out a bit, and we positioned our background images to the right of each box with some padding applied to keep the content out of the way. Now with a couple of typographical tweaks we can probably wrap up this project. To these indicated rules, add the items in bold:

name {
    display:block;
    font-weight:bold;
    font-style:italic;
    font-size: 1.3em;
    font-family: "Trebuchet MS", Verdana, Helvetica, sans-serif;
    color:#333;
}
work {
    display: list-item;
    list-style-type: square;
    margin-left:2em;
}
title {
    font-style:italic;
    border-bottom:1px dotted #ccc;
}
period {
    display:block;
    font-style:italic;
    margin-bottom:0.5em;
}
instrumentation {
    text-transform: lowercase;
}
date:before {
    content: "(";
}
date:after {
    content: ")";
}
instrumentation:before {
    content: "for ";
}

Our final touches to our style sheet will show up as shown in Figure 9-8.

Image

Figure 9-8. The final styling for our composers XML file

With those additions, we've finished up making a raw XML file turn into a rather attractive and readable page, which was our goal for this project. For the name of the composer, which includes the <givenname> and <surname> values, we styled it to be more of a heading-like object with a stylistic sans-serif font, slightly larger, and in a lighter shade. For the <instrumentation> element, we have to transform it to lower case, since some of the values have capitalization that doesn't look right in the final output. Here is our final style sheet in its entirety:

composers {
    background-color:#4C4C4C;
    padding-top:4em;
    font-family:Georgia, serif;
    font-size:0.95em;
}
composer {
    display:block;
    margin:0 auto 1em auto;
    padding:1em;
    padding-right:150px;
    background-color:#fff;
    width:40%;
    border-bottom:1px dotted #ccc;
    background-position:96% 1em;
    background-repeat:no-repeat;
}

composer[id="mahler"] { background-image: url(img/mahler.jpg); }
composer[id="bach"] { background-image: url(img/bach.jpg); }
composer[id="shostakovich"] { Image
    background-image: url(img/shostakovich.jpg); }
composer[id="beethoven"] { background-image: url(img/beethoven.jpg); }
composer[id="schubert"] { background-image: url(img/schubert.jpg); }
composer[id="stravinsky"] { Image
    background-image: url(img/stravinsky.jpg); }
composer[id="dvorak"] { background-image: url(img/dvorak.jpg); }
composer[id="wuorinen"] { background-image: url(img/wuorinen.jpg); }

name {
    display:block;
    font-weight:bold;
    font-style:italic;
    font-size: 1.3em;
    font-family: "Trebuchet MS", Verdana, Helvetica, sans-serif;
    color:#333;
}
work {
    display: list-item;
    list-style-type: square;
    margin-left:2em;
}
title {
    font-style:italic;
    border-bottom:1px dotted #ccc;
}
period {
    display:block;
    font-style:italic;
    margin-bottom:0.5em;
}
instrumentation {
    text-transform: lowercase;
}
date:before {
    content: "(";
}
date:after {
    content: ")";
}
instrumentation:before {
    content: "for ";
}
yearbirth:before {
    content: "b.";
}
yeardeath:before {
    content: "- d.";
}
favoriteworks:before {
    content: "Favorite works";
    font-weight:bold;
}

Summary

XML is a largely untapped realm when it comes to applying CSS, making it an interesting area for exploration. More often an XSL transformation is applied and the document is made to produce good ol' HTML before applying any CSS, or the document is fully handled using XSL-FO. However, following the principles of using the Rule of Least Power that we discussed earlier, CSS may very well be a fine choice for a large number of jobs. It is a skill you're already familiar with by now, and it may warrant consideration should you ever be presented with the task of having to put some polish and shine on a piece of XML.

With good support for basic XML styling using CSS among most of the major browsers today, styling XML using CSS is certainly worthy of consideration for your projects. Use CSS to style your XML documents whenever possible, and use the simpler CSS option over the more complex process of XSL for styling your documents, if the former will suit the needs of the project.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset