
A Confusion of Styles
Q: How do I style a custom element's content?
I want two elements (QUESTION and ANSWER) to be declared in an external DTD. The QUESTION element's data is to be displayed in red, and the ANSWER element's data is to be displayed in green. For this, an external stylesheet needs to be used. How do I include the DTD in my HTML document?
Here's the relevant code:
queans.dtd:
<?xml-stylesheet type="text/css"
href="clr.css"?>
<!ELEMENT QUESTION (#PCDATA)>
<!ELEMENT ANSWER (#PCDATA)>
clr.css:
<STYLE>
QUESTION {font-family:arial;font-size:20pt;color:#ff0000}
ANSWER {font-family:arial;font-size:20pt;color:#00aa00}
</STYLE>
sample.htm:
<!DOCTYPE SYSTEM "queans.dtd">
<HTML>
<BODY>
<QUESTION>What is your favorite web
site?</QUESTION>
<ANSWER>My favorite web site is
www.xml.com.</ANSWER>
</BODY>
</HTML>
A: As you've no doubt discovered, if you open this sample.htm in your
favorite browser, you'll see the content of the QUESTION and
ANSWER elements all right but displayed in the browser's
default font (family, size, and color). You can fix this, but you'll have
to straighten out some major misunderstandings first.
To recap, you've got a DTD which defines a couple of elements; a
Cascading Style Sheet which contains a STYLE element; and an
HTML document which (via the DOCTYPE declaration) points to
the DTD and includes both elements defined there, plus a couple of others
(HTML and BODY). Among the numerous confusions
at work here:
- First, you don't need a DTD if all you want is to style an XML element's content when viewed in a browser. (I'll show you how to do this later.)
- Second, you really can't customize an HTML document by adding non-HTML
elements (such as
QUESTIONandANSWER), using a DTD or by any other means. Browsers employ a variety of techniques to determine what sort of file or document they're asked to present to the user. (The simplest of these, also arguably the most common, is to look at the file's extension.) If a browser thinks it's reading an HTML document, it will display "known" HTML elements according to its default settings (for font, color, and so on) for that element -- unless overridden by a stylesheet. When it encounters an unknown element, however, all bets are off: it just displays the content in the same font, etc., used for plain old text (such as text contained in apelement). Thus, your sample.htm file isn't a true HTML document; it's not even an XHTML document, but a document employing a hybrid, HTML-like XML vocabulary. - Third, if for some other reason you want to use a DTD, it needs to spell out everything which can be encountered in a document conforming to the DTD. If a document referencing the DTD includes HTML and BODY elements, then those elements must be declared in the DTD.
- Fourth, the association between a stylesheet and the content to be
displayed is never made in a DTD, or anywhere else for that matter, but in
the document where the content is found. Note that this is true for both
XML documents -- including XHTML ones -- and garden-variety HTML ones.
- If you're working with a non-(X)HTML vocabulary, use an
xml-stylesheetprocessing instruction just like the one you've mistakenly placed in your DTD. - If you're working with (X)HTML, place the reference to the external
stylesheet in a
LINKelement -- again, in the document where the content resides (sample.htm, in this case). (If you're using XHTML-with-an-X, all element and attribute names must be lowercase. ThusLINKbecomeslink,BODYbecomesbody, and so on.)
- If you're working with a non-(X)HTML vocabulary, use an
- Finally, in a CSS stylesheet, there's never anything but the style
specifications: you especially don't include anything that looks like XML
or HTML (like the
STYLEelement you've placed in clr.css).
If contemplating all of this hasn't completely exhausted you, here are some alternative solutions to your problem.
Simple customized display of an XML document
With this approach, as I said, you don't need a DTD at all. Just point the XML document to the right stylesheet. Corrected versions of your documents would then look as follows:
clr.css:
QUESTION
{font-family:arial;font-size:20pt;color:#ff0000}
ANSWER
{font-family:arial;font-size:20pt;color:#00aa00}
sample.xml:
<?xml-stylesheet type="text/css"
href="clr.css"?>
<HTML>
<BODY>
<QUESTION>What is your favorite web
site?</QUESTION>
<ANSWER>My favorite web site is
www.xml.com.</ANSWER>
</BODY>
</HTML>
Results when viewed in Mozilla:
(The Internet Explorer display is identical, except for the browser "chrome" of course.)
Simple display of an XHTML document
This is a little more complex, but still simple. The stylesheet remains
the same as above. In the document itself, as I said, change all uppercase
element and attribute names to lowercase. Furthermore, while it's not
absolutely essential in the almost-anything-goes world of browsers, you
should formally associate your document with the XHTML vocabulary in two
ways:
(1) use a DOCTYPE declaration which points to the XHTML DTD of
your choice, and (2) use an xmlns attribute -- that is, a namespace
declaration -- to assert which of the document's elements are in the XHTML
namespace. (Typically, all elements in an "XHTML" document are in
the XHTML namespace, but this needn't strictly be the case.) And finally,
of course, you must add a link element to connect your
document to clr.css.
At this point, sample.htm will now resemble the following
(assuming you want to use the XHTML "transitional" vocabulary), with the
most significant changes in boldface:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/TR/1999/REC-html-in-xml">
<link rel="stylesheet" type="text/css" href="clr.css"
/>
<body>
<QUESTION>What is your favorite web
site?</QUESTION>
<ANSWER>My favorite web site is
www.xml.com.</ANSWER>
</body>
</html>
In this case, browser behavior diverges: Mozilla's display of the content matches that of the previous solution. Internet Explorer, however, displays the question and answer in the browser's default font (family, size, and color). The "problem," I think, is that IE still doesn't recognize your QUESTION and ANSWER elements as XHTML. (Understandably, I might add. This seems to be a more correct behavior than Mozilla's.)
The only way to fix this is to replace your QUESTION and ANSWER
elements with true XHTML elements, differentiating between them using
class attributes. Something like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/TR/1999/REC-html-in-xml">
<link rel="stylesheet" type="text/css" href="clr.css"
/>
<body>
<span class="QUESTION">What is your
favorite web site?</span>
<span class="ANSWER">My favorite web
site is www.xml.com.</span>
</body>
</html>
The implication of this change is that you must also change
clr.css's selectors; here's a general solution:
.QUESTION
{font-family:arial;font-size:20pt;color:#ff0000}
.ANSWER
{font-family:arial;font-size:20pt;color:#00aa00}
(The dot preceding each selector associates that style with any element
which has a class attribute with the indicated value.)
Now both browsers again behave identically.
|
Also in XML Q&A | |
Getting fancier...
I don't mean "fancier" in terms of the display; I mean it in terms of
how to attain your objective. This solution builds on the
previous one; it assumes that you truly do need those non-(X)HTML elements
in your document, and you want to use the uppercase element names. It
simplifies some things, such as sample.htm itself (which
returns to something very like its original form). The complexity comes
from the addition of a second stylesheet -- this one in XSLT. Your
document would now look something like this:
<?xml-stylesheet type="text/xsl"
href="clr.xsl"?>
<HTML>
<BODY>
<QUESTION>What is your favorite web
site?</QUESTION>
<ANSWER>My favorite web site is
www.xml.com.</ANSWER>
</BODY>
</HTML>
The XSLT stylesheet in question would specify the transformation of
this simplified sample.htm into a result tree which more or
less matches the version of sample.htm in the previous
solution. Here's an XSLT stylesheet (just one of many approaches,
depending on how rigorous you need it to be) to accomplish this:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/1999/REC-html-in-xml">
<xsl:output method="xml"
version="1.0"
doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
/>
<xsl:template match="HTML">
<html>
<link rel="stylesheet" type="text/css" href="clr.css"
/>
<xsl:apply-templates />
</html>
</xsl:template>
<xsl:template match="BODY">
<body><xsl:apply-templates /></body>
</xsl:template>
<xsl:template match="QUESTION | ANSWER">
<span class="{name()}"><xsl:apply-templates
/></span>
</xsl:template>
</xsl:stylesheet>
(I'll leave readers to extract from this example those bits which most interest them.)
And how, you might wonder, do the browsers treat
sample.htm now? Sadly, they ignore -- at least under Windows
-- the result tree from this transformation; indeed they don't attend to
the xml-stylesheet declaration at all. I suspect this is because of that
operating system's stubborn reliance on filename extensions to determine
how to treat the document: .htm (or .html) means
the document is an (X)HTML document and damn the consequences.
Accordingly, sample.htm displays exactly as it did way back
at the beginning of this answer, in default fonts and colors.
(Rather than shake your head in misery at this point, you might try
changing the extension to .xml. Test it in both
browsers. You'll find something else to shake your head over.)
For what it's worth, if you run this most recent version of
sample.htm through a standalone XSLT engine like Saxon,
you'll see the result tree you need:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/TR/1999/REC-html-in-xml">
<link rel="stylesheet" type="text/css"
href="clr.css"/>
<body>
<span class="QUESTION">What is your favorite web
site?</span>
<span class="ANSWER">My favorite web site is
www.xml.com.</span>
</body>
</html>
If you save this result tree to a separate file, the browsers handle it just fine (and identically).
You may find this last alternative -- even though it's in some ways the most correct, requiring the least modification to your original source document -- a bit out of reach for now. Don't despair. Just keep asking questions and doing research.
- Wrong Namespace
2004-02-02 23:05:02 Christian Schmidt-Guetter - Wrong Namespace
2004-02-03 05:48:11 John Simpson