A Confusion of Styles
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:
QUESTION and ANSWER), 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 a p
element). 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.xml-stylesheet processing instruction just like the one
you've mistakenly placed in your DTD.LINK element -- 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. Thus
LINK becomes link, BODY becomes
body, and so on.)STYLE element you've placed in
clr.css).If contemplating all of this hasn't completely exhausted you, here are some alternative solutions to your problem.
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.)
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 | |
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.
XML.com Copyright © 1998-2006 O'Reilly Media, Inc.