原始版本: http://www.w3.org/Style/styling-XML

翻译: Shanghai.ws

声明:原始版本(英文版)是唯一的官方版本。中文(简体)版本是根据W3C网站上的文件翻译的,可能存在某些错误。翻译不保证译文完全准确。请您自己承担风险。


如何给XML添加样式

(This page uses CSS style sheets)

样式

该选用哪一种?

外部

CSS

嵌入式

XSL

CSS2 推荐包含一个关于使用XML,CSS的简短的教程(见§ 2.2)。当编写CSS2的时候,官方的XML的样式规范还没有准备。这就是那个教程里应该包含的内容。注意例子使用CSS,但是大多数情况下,那些样式规则也能用XSL编写。

外部样式表

Tip: 请在你的浏览器里试一试

HTML有一个link元素 来链接外部样式表,但是并不是每个基于XML的格式都会有这样一个元素。如果没有适合的元素,你仍然可以通过附加外部样式表xml-stylesheet处理指令的方法,如下:

<?xml-stylesheet href="my-style.css" type="text/css"?>
... rest of document here...

这个处理指令(PI)必须放在文档第一个标签的前面。type="text/css"不是必需的,但是这个能够帮助浏览器:如果它不支持CSS,它就知道它不会需要下载此文件。

只要用HTML的link元素,就会有复合的xml-stylesheet处理指令,它们有设置类型、媒介和标题的属性。

这里有大量的例子。假设我们有三个样式表,一个设置各个元素的基本显示类型(内联,段,列表条目等等)。还有两个不同的,分别设置颜色和页边距。后面的两个是二选一的,文档的读者可以选择使用其中一个。除非要打印文档,那样我们就必须选择最后那种。下面是普通样式表:

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

这是替代样式表之一,在文件里称为“modern.css”:

/* 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 }

这还有另外一个,称为“classic.css”:

/* 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 }

有这三个样式表链接的XML文档看起来是这样的:

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

<?xml-stylesheet href="modern.css" title="Modern" media="screen"
  type="text/css"?>
<?xml-stylesheet href="classic.css" alternate="yes"
  title="Classic" media="screen, print" type="text/css"?>
<ARTICLE>
  <HEADLINE>Fredrick the Great meets Bach</HEADLINE>
  <AUTHOR>Johann Nikolaus Forkel</AUTHOR>
  <PARA>
    One evening, just as he was getting his 
    <INSTRUMENT>flute</INSTRUMENT> ready and his
    musicians were assembled, an officer brought him a list of
    the strangers who had arrived.
  </PARA>
</ARTICLE>

有关更多的详情,见W3C推荐“结合XML文档样式表”

嵌入式样式表

Tip: 请在你的浏览器里试一试

HTML有一个style元素,可以让样式表直接嵌入HTML文件里,而不需要外部文件。在某些情况下这个更容易,尤其是当该文档里的样式表非常特定的时候。

大多数基于XML的格式不会有这样的一个元素,但是同样的链接到外部样式表的处理指令,也能用来指向在文档本身嵌入的样式表。截止2006年2月,这个还是存在一个技术问题,也没有正式的规范存在。例如:

<?xml-stylesheet href="#style" type="text/css"?>
<ARTICLE>
  <EXTRAS id="style">
    INSTRUMENT { display: inline }
    ARTICLE, HEADLINE, AUTHOR, PARA { display: block }
    EXTRAS { display: none }
  </EXTRAS>
  <HEADLINE>Fredrick the Great meets Bach</HEADLINE>
  ...
</ARTICLE>

在这种情况下,type="text/css"属性必须存在,否则浏览器(或是其它的应用程序)必须要猜测样式表的语言。xml-stylesheet处理指令现在没有指向一个外部样式表,但是指向了文档本身的一个元素。那是一个由id属性定义的元素,作为连接的标签服务的。(决定于特殊的XML格式,id属性可能会被称作其它的;在某些格式里,可能会根本没有一个适合的属性。)

未解决的问题

W3C推荐“结合XML文档样式表”没有定义嵌入式样式表的情况,尽管看起来似乎是一个合理的推断,让URL片段(用一个“#”开始的)。这时,2006年初,仍然有没解决问题,也没有颁布规范。问题如下:

  1. 因为嵌入式样式表不是从服务器上单独下载的,服务器就不能告诉浏览器样式表的格式是什么。因此,在这种情况下就需要type属性。不确定会怎样,如果这个属性缺失:样式表被忽略?如果假设是CSS呢?是否有什么算法可以确定这个语言呢?
  2. 大多数基于XML的格式,一个片段识别码定义一个完整的元素,而不是一个元素的内容。但是一个用“ARTICLE”开始的样式表不是正确的CSS,所以似乎需要额外的规则:一个样式表处理指令里使用的片段识别码,指向一个元素的内容而不是元素本身。
  3. 类似的情况,如果指向的是元素里的一个子元素,也不能确定会怎样。是不是组成样式列表的全部元素的所有内容都是串联的?只是第一个元素的内容?或只是一个错误,还是整个元素都忽略了?
  4. 在上面的例子里,URL指向文档本身。事实是,浏览器能够读取在那个URL的所有指令,它知道如何分析XML,也有找到指令样式元素的能力。但是现在想想指向一个外部文档的某片段的一个URL。为了成功的回复样式表,浏览器必须先下载在解析外部的文档,然后提取和分析出样式表。但是type属性只给出了两者之间一个的类型,所以浏览器不知道是否可以用这个样式表。它没有,甚至没有定义type属性给出的外部文档类型或是嵌入在里面的样式表。
  5. 使用“Generic XML”,样式表处理指令最有用,例如:在格式里使用浏览器不知道的XML。多亏样式表,至少还能显示一些东西。有名的格式,如:SVG,SMIL或XHTML,虽然有它们自己的规则来转换,但超过了一个样式表能指定的。而当文档当做Generic XML看待时,有些其它的东西浏览器还是不知道:特别是,它不知道那个属性是ID属性。有一个关于被称作xml:id属性的W3C推荐,若果文档中有包含那个名字的属性,很可能URL片段会指向这些的其中一个。但如果没有这样的属性,浏览器一定会尝试其它的方法来决定哪些属性是IDs。如果文档有一个DOCTYPE在顶部,浏览器就能回复它指向的DTD,DTD也会指定属性。但是浏览器可能不能读出DTDs或是没有一个DOCTYPE。
  6. 在文档里,一个片段ID是唯一的指向一个元素的方法,另外一个W3C推荐定义了XPointers来辨别文档里的元素,而不用ID属性。但是浏览器使用样式表处理指令,目前还没有要理解XPointers的这个要求,因此就不清楚是否浏览器需要解释XPointers,是否它们能,还是它们必须忽略。

内联定义

HTML也允许通过style属性的方法,把样式直接附加到单个元素。大多数基于XML的文档格式没有这样的一个属性,虽然有些允许让来自HTML的功能()在文档内使用。

类别属性

Tip: 请在你的浏览器里试一试

class属性允许你创建HTML元素子类别,但不太可能在大多数基于XML文档格式里提供。当然,CSS让你能够在任何属性的基础上选择元素,不仅仅是class,但是句法就没有那么方便。

这里有一个例子。如果有一个class属性,文档格式定义它在HTML里工作,我们可以用点符号。(因此,这个特殊的例子就不会工作了,因为<doc>不是像class那样能够让浏览器知道的格式。)

<?xml-stylesheet href="#s1" type="text/css"?>
<doc>
  <s id="s1">
    s { display: none }
    p { display: block }
    p.note { color: red }
  </s>
  <p>Some text... </p>
  <p class="note">A note... </p>

</doc>

如果文档格式没有指定class创建一个子类别,接下来你必须要使用带有“[ ]”的更长的选择器:

<?xml-stylesheet href="#s1" type="text/css"?>
<doc>
  <s id="s1">
    s { display: none }
    p { display: block }
    p[class~=note] { color: red }
  </s>
  <p>Some text... </p>
  <p class="note">A note... </p>

</doc>

如果没有class属性,但是有其它我们可以使用的,属性选择器“[ ]”仍然适用:

请在你的浏览器试一试

<?xml-stylesheet href="#s1" type="text/css"?>
<doc>
  <s id="s1">
    s { display: none }
    p { display: block }
    p[warning="yes"] { color: red }
  </s>
  <p>Some text... </p>
  <p warning="yes">A note... </p>

</doc>
Bert Bos
Created 29 February 2000 (last update: $Date: 2009/12/15 20:59:04 $)