XML简易教程
2008-09-10 11:46
在Intel的早期,Andy Grove遇到一个雇员 - 他
建议公司在芯片的基础上开发个人计算机。Andy Grove疑问道“个人计算机能做什么呢?”,这个 雇员举例说,它可以存储处方。Grove考虑到整个 研究、开发和市场费用要数百万美圆,最终决定 以为红绿灯提供芯片作为开始。 每个人都是事后诸葛亮。Andy Grove,不管你怎样看他,被普遍 认为是一个非常聪明的人 - 能够做出发展公司的重大决定。但 是在七十年代,不可能强求他预见到个人计算机的潜力。如果 他当时见过Excel、Quark、Photoshop、Oracle或者网络,他就会 理解把强大的处理器放在桌面上会允许软件做任何事。
但是如果没亲眼见过,谁能想到呢。在用打字机、加法机和铅
笔作为计算的工具的时代,你能解释PC和它的用途吗?
这个例子可以用在解释扩展标记语言(XML - eXtensible Markup
Language)上。现在还没有和它相似的东西,所以很难做出比 较。你可能听说过XML是HTML的替代物或XML与HTML相似,可以 定义自己的标记符。这两种说法都不全对,就象说PC是存储处 方的机器一样。
我妈妈是一个训练有素的厨师,如果我用她的配方,我的家庭
会省下很大一笔钱。
我以简单的开始。因此我打开文本编辑器,开始写一些HTML
代码:
<HTML>
<H1 ALIGN=CENTER>Recipe</H1>
<FONT FACE size=2>Chocolate Chip Bars</FONT>
在写完上面几行后,我想接着写我妈妈 的精妙菜谱。那么怎么
做呢?一份老式的Web页面。接下来呢?把我的页面的URL送给 对这个菜谱感兴趣的人们,然后让他们剥掉其中的<P>和<FONT FACE size=2>吗?这得花些时间,我想得到实际的内容。
看看下面可能的XML标记:
<author>Carol Schmidt</author>
<recipe_name>Chocolate Chip Bars</recipe_name>
在XML中,标记符可以最好地描述内容。以这种方式,我可以肯
定任何查找出现在<recipe_name>标记符中的“Chocolate Chip” 的人都可以得到妈妈_的菜谱。进一步说,如果我的信息被象这 样的标记符(有意义的标记符)包围 - 我可以告诉其它程序如 何使用它们。我还可以通过编码把<recipe_name>标记符中的内 容放入数据库的某个域中,然后把它输出到一本书的硬拷贝中。 还有,我可以用一个支持XML的字处理器使网页的出版轻而易举。
这就是XML的本质:使标记对人和机器都可读。但是在实现这个
目标之前,应该理解用XML编码所涉及的东西。
文档要组织良好
一个XML文件必须满足两点:组织良好和有效。我们以一个组 织良好的文档开始。
我发明了一些描述菜谱的标记符,并把它们组织成一种合理
和可读的方式。它可能不是最好的标记,但是在下面的例子 中工作得很好。
<?xml version="1.0"?>
<list> <recipe> <author>Carol Schmidt</author> <recipe_name>Chocolate Chip Bars</recipe_name> <meal>Dinner <course>Dessert</course> </meal> <ingredients> <item>2/3 C butter</item> <item>2 C brown sugar</item> <item>1 tsp vanilla</item> <item>1 3/4 C unsifted all-purpose flour</item> <item>1 1/2 tsp baking powder</item> <item>1/2 tsp salt</item> <item>3 eggs</item> <item>1/2 C chopped nuts</item> <item>2 cups (12-oz pkg.) semi-sweet choc. chips</item> </ingredients> <directions> Preheat oven to 350 degrees. Melt butter; combine with brown sugar and vanilla in large mixing bowl. Set aside to cool. Combine flour, baking powder, and salt; set aside.Add eggs to cooled sugar mixture; beat well. Stir in reserved dryingredients, nuts, and chips. Spread in greased 13-by-9-inch pan. Bake for 25 to 30 minutes until goldenbrown; cool. Cut into squares. </directions> </recipe> </list> 这就是一份可以接受的XML文档 - 告诉你XML是什么:把数据 以一种有实际意义的方式进行组织。
虽然这些标记符看起来有点象HTML,但是有很大的区别:文件
中没有指出数据如何表示的信息。版面指令,当我们准备好时, 就会从其它地方出现。这和把地址簿的信息放在数据库的字段 和记录中而不是放在字处理器产生的清单中的道理一样。数据 库可以让你把地址簿中的信息合成到标签、信封、信件或其它 任何想要的载体上面。最后,就是把这份菜谱文件合成到一种 表现语言中,如HTML或CSS。
前面说过,XML文档必须组织良好。这意味着文件必须满足以下
三项基本规则:
文档以XML定义<?xml version="1.0"?>开始。
有一个包含所有其它内容的根元素,如上面例子中的<list> 和</list>标记符。 所有元素必须合理地嵌套,不允许交叉嵌套。 上面的例子中,几个<item>元素被合理地嵌套<ingredients>和 </ingredients>标记符中。但是下面的标记却有严重的问题:
<ingredients><item></ingredients>chocolate chips</item>
于是"chocolate chips"没有被包含在ingredients清单中。因此
这份文档就没有组织好。这在HTML中可能不算什么,因为浏览器 已经被设计成可以处理这种问题。
但是在XML中却是致命的 - 应用程序将拒绝处理没有组织好的
文件。
我们现在知道组织良好非常重要,但是还不止这些
文档格式的排错
我妈妈_的清单中有数十条菜谱,甚至数百条。如果产生一个致 命错误,排错将非常困难 - 你将一行一行地寻找丢失的标记 符。如果使用几层嵌套,发现错误将很困难。
但是可以找到很好的帮助。分析器 - XML代码和报告格式错误
的应用程序可以在网上免费得到。其中最好的是Lark,它的作 者是由Tim Bray - XML规范的技术编辑和极力鼓吹者,地球上最 聪明的人之一。
我用Lark分析下面的代码。注意"chocolate chips"和它的关闭
标记符出现在</ingredients> 标记符中的位置有错误:
<?xml version="1.0"?>
<list>
<recipe>
<author>Carol Schmidt</author>
<recipe_name>Chocolate Chip Bars</recipe_name>
<meal>Dinner
<course>Dessert</course>
</meal>
<ingredients>
<item>2/3 C butter</item>
<item>2 C brown sugar</item>
<item>1 tsp vanilla</item>
<item>1 3/4 C unsifted all-purpose flour</item>
<item>1 1/2 tsp baking powder</item>
<item>1/2 tsp salt</item>
<item>3 eggs</item>
<item>1/2 C chopped nuts</item>
<item>
</ingredients>2 cups (12-oz pkg.) semi-sweet choc.
chips</item>
<directions>
Preheat overn to 350 degrees. Melt butter;
combine with brown sugar and vanilla in large mixing bowl.
Set aside to cool. Combine flour, baking powder, and salt; set aside.
Add eggs to cooled sugar mixture; beat well. Stir in reserved dry
ingredients, nuts, and chips.
Spread in greased 13-by-9-inch pan. Bake for 25 to 30 minutes
until golden brown; cool. Cut into squares.
</directions>
</recipe>
</list>
下面是分析器返回的结果:
Error Report
Line 17, column 22: Encountered </ingredients> expected </item>
... assumed </item>
Line 18, column 36: Encountered </item> with no start-tag.
有了这种信息,找到错误将不会成为问题。那么XML文件的有效性
是指什么呢?
实现有效性
最终我们将在组织良好的XML文档中加入信息。实际上,我们 有很多事要做 - 仍然有危机潜伏 - 虽然XML文件组织良好, 但还可能丢失关键信息。看看下面的例子:
<recipe>
<author>Carol Schmidt</author> <recipe_name>Chocolate Chip Bars</recipe_name> <meal>Dinner <course>Dessert</course> </meal> <ingredients> </ingredients> <directions>Melt butter; combine with, etc. ... </directions> </recipe> 这份菜谱中没有包含ingredient,而且因为它组织良好,所以 Lark分析器也不会发现问题。管理过哪怕是最和善的数据库的 人都知道我们人类常犯的错误:如果有机会,我们会丢掉关键 信息并加入无用的废话。这就是为什么XML的发明者引入DTD - 文档类型定义(Document Type Definition)。DTD提供了一种保 证XML或多或少是你所想的方法。
让我们看看用在菜谱上的一个DTD。
<!DOCTYPE list [
<!ELEMENT recipe (recipe_name, author, meal, ingredients, directions)> <!ELEMENT ingredients (item+)> <!ELEMENT meal (#PCDATA, course?)> <!ELEMENT item (#PCDATA, sub_item*)> <!ELEMENT recipe_name (#PCDATA)> <!ELEMENT author (#PCDATA)> <!ELEMENT course (#PCDATA)> <!ELEMENT item (#PCDATA)> <!ELEMENT subitem (#PCDATA)> <!ELEMENT directions (#PCDATA)> ]> 这些代码起初看起来不够友好,但当把它分解时却能看出其中 的意义。让我们详细解释之:
<!DOCTYPE list [
这行是说,包含在方括号中的是具有根元素<list>的某个文档的
DTD。如我们以前提到的,根元素包含所有其它元素。
<!ELEMENT recipe (recipe_name, meal, ingredients, directions)>
这行定义了<recipe>标记符。圆括号是说其中的四种标记符必
须按照顺序出现在<recipe>标记符中。
<!ELEMENT meal (#PCDATA, course?)>
这行需要详细的解释。我定义了以下的结构:
<meal>Here the meal name is mandatory
<course>One course name may appear, but it is not mandatory</course> </meal> 我这样做是因为,按照我的想法,午餐不一定特定某道菜,但 是晚餐可能要指出开胃食品、主菜和餐后甜点。通过指定 #PCDATA - 表示经过分析的字符数据(即非二进制数据)来 实现这个功能。这里,#PCDATA是文本 - 例如,“dinner”。
"course"后面的问号表示0或1对<course>标记符将出现在<meal>
标记符内。
现在让我们看看下一行:
<!ELEMENT ingredients (item+)>
这里的加号表示至少有一对<item>标记符应出现在<ingredients>
标记符内。
我们感兴趣的最后一行是:
<!ELEMENT item (#PCDATA, sub_item*)>
我把sub_item*作为一项安全措施。除了要求每个item的文本之
外,我希望计算每个item的内容的数量。星号是说在<item>标记 符中可以有子条目的数目。我不需要Chocolate Chip Bars菜谱的 任何子条目,但是当它的组成成分很复杂时就用得着。
现在让我们把这些放在一起看看我们能得到什么。
DTD的完整例子
下面是一个完整的例子。我把另一个菜谱加入文件内,并为 DTD做了注释。可以注意到我在第二个菜谱中用到子条目。
<?xml version="1.0"?>
<!--This starts the DTD. The first four lines address document structure--> <!DOCTYPE list ][ <!ELEMENT recipe (recipe_name, author, meal, ingredients,directions)> <!ELEMENT ingredients (item+)> <!ELEMENT meal (#PCDATA, course?)> <!ELEMENT item (#PCDATA, sub_item*)> <!--These are the remaining elements of the recipe tag --> <!ELEMENT recipe_name (#PCDATA)> <!ELEMENT author (#PCDATA)> <!ELEMENT directions (#PCDATA)> <!--The remaining element of the meal tag --> <!ELEMENT course (#PCDATA)> <!--The remaining element of the item tag --> <!ELEMENT sub_item (#PCDATA)> ]>
<?xml version="1.0"?>
<list> <recipe> <author>Carol Schmidt</author> <recipe_name>Chocolate Chip Bars</recipe_name> <meal>Dinner <course>Dessert</course> </meal> <ingredients> <item>2/3 C butter</item> <item>2 C brown sugar</item> <item>1 tsp vanilla</item> <item>1 3/4 C unsifted all-purpose flour</item> <item>1 1/2 tsp baking powder</item> <item>1/2 tsp salt</item> <item>3 eggs</item> <item>1/2 C chopped nuts</item> <item>2 cups (12-oz pkg.) semi-sweetchoc. chips</item> </ingredients> <directions> Preheat oven to 350 degrees. Melt butter; combinewith brown sugar and vanilla in large mixing bowl. Set aside to cool. Combine flour, baking powder, andsalt; set aside.Add eggs to cooled sugar mixture; beat well. Stir in reserved dry ingredients, nuts, and chips. Spread in greased 13-by-9-inch pan. Bake for 25 to 30minutes until golden brown; cool. Cut into squares. </directions> </recipe> <recipe> <recipe_name>Pasta with tomato Sauce</recipe_name> <meal>Dinner <course>Entree</course> </meal> <ingredients> <item>1 lb spaghetti</item> <item>1 16-oz can diced tomatoes</item> <item>4 cloves garlic</item> <item>1 diced onion</item> <item>Italian seasoning <sub_item>oregano</sub_item> <sub_item>basil</sub_item> <sub_item>crushed red pepper</sub_item> </item> </ingredients> <directions> Boil pasta. Sauté garlic and onion. Add tomatoes.Serve hot. </directions> </recipe> </list> 既然有DTD,文档将被检查看是否符合DTD做出的限制。换句话 说,我们要保证文档的有效性。
为了达到这个目的,我们需要另一个工具:有效性分析器。微软
的MSXML,一个基于Java的程序,使用容易又工作得很好。上面的 文档经过这个程序的检查后没有发现错误。但是如果我检查一个 ingredient标记符中没有包含条目的菜谱,将会返回以下信息:
ingredients is not complete. Expected elements [item].
XML的未来
现在你已经知道XML。确实,结构有点复杂,而且DTD有各种可 以定义文档可以包含的内容的选项。但还不只这些。
考虑一个数据交换对其很重要的产业,如银行。银行使用所有
权系统来跟踪内部的交易,但是如果他们在Web上使用一种通用 的XML格式,那么他们必须描述交易信息给另一个机构或应用程 序(如Quicken或MS Money)。当然,他们也可以在Web页面上 表示数据。FYI:这个标记不存在。它叫做OFEX,开放金融交易 格式(Open Financial Exchange)。
在某种情况下,如果PC上的IE 4碰到一个<SOFTPKG> 标记符,一
个函数会被启动以给用户更新已安装的软件的机会。如果你用 的是Windows 98,你可能看见过这种情况,但是不知道它是一 个XML应用程序。
这里我们有三个XML应用程序,看起来与Andy Grove在70年代看
到的加法机、打字机和铅笔不同。但是与最终出现在PC上的应 用程序相似,XML的好处可以被一般性地描述为:“当你使用人 类和机器可读的标记符描述你的数据时,会有好事发生的。”
这些好事是什么呢?我不知道。但是我也不知道我的PC上的下
一代程序将会是什么样。只要数据以这种方式标记,可以产生 不同的应用。
你开始考虑它会扩展到什么程度了吗?
我们有很多XML的实际应用可以谈论,我会在不久的将来谈到它
们的。既然我们都是网民,以后将是XSL(扩展样式语言 - eXtensible Style Language)了。
顺便提一句,这个菜谱确实是我妈妈_的,而且很杰出。如果你
用之,再加半杯碎椰子。 我写这篇文章是因为我真诚地关心你对我的看法。我担心的是:如果你读过我写的XML简介然后准备开始写自己的XML文档。于是你开始寻找一个已经建立的DTD来表示你的信息。你找到一个,如下所示:
<!ATTLIST fn
%attr.lang;
value CDATA #FIXED "TEXT">
<!ENTITY % attr.img "
img.type CDATA #REQUIRED
img.data ENTITY #REQUIRED">
马上你就会认为Jay一定是一个白痴。他没有说关于ATTLIST和ENTITY的任何事 - 不管它们是什么。
那么让我们谈谈这件事,先有一点耐心。
上面这些行可能不好看,但实际上没什么。它们被用在DTD中来定义XML文档中的属性和实体。了解HTML的人会对这很清楚。属性是带有HTML标记符的条目,用来更准确地描述标记符。在经常出现的<img src="my.gif" height="20" width="20">中,有两个属性:height和width。你在后面会看到,在XML文档使用属性与之很相似。
对实体也没有什么新东西。如果你用过&,你就已经掌握了最基本的东西。一个被&和分号包围起来的字符串用来表示另一个或一套字符。(这里有ISO实体的完整清单。)
当然,XML中属性和实体还有其它功能。这就不可避免地要引入语法,虽然不太多。一旦知道了这些,就会不费劲地使用XML文档。
简化菜谱
如果你读过我写的XML简介,你会记得用简单的标记符表示的菜谱中的组成成分,如<item>2 cups flour</item>。在写完那篇文章后,我在网上漫游,发现关于菜谱的另一个XML文档。其中的菜谱元素如下所示:
<ingredient quantity="2" units="cups">flour</ingredient>
这种方法有一个实际的好处:可以更容易控制数据。用第一种方法,<item>标记符用来容纳一堆不同的信息。如果我想提取组成成分的清单而不需要各成分的量,我就不会那么做。
我可以用如下的结构取得相似的功能:
<item>flour
<quantity>2</quantity>
<units>cups</units>
这可以被处理,但是有两个问题:首先,item元素包含了混合的内容:文本和其它标记符。我很快就发现应该尽量避免这种结构。其次是标记符几乎没有独立的意义。很难想象只要units而不要实际的组成成分的情况。这些条目可以被简单描述,我宁愿把它们当作属性。
首先要注意的是属性名,quantity和units只有被能够翻译它们的应用程序处理时才有意义。
在被包含在有效的文档中之前,应告诉DTD来允许它。对于上面的ingredient元素,我们在DTD中只包含了以下代码:
<!ELEMENT ingredient #PCDATA>
<!ATTLIST ingredient quantity CDATA #REQUIRED>
<!ATTLIST ingredient units CDATA #REQUIRED>
第一行看起来很熟悉 - 在任何DTD中都能看到的标准元素定义。每个ATTLIST行都依次包含以下信息: <!ATTLIST ingredient quantity CDATA #REQUIRED>
这是属性依附的元素。
<!ATTLIST ingredient quantity CDATA #REQUIRED>
这里定义属性名。
<!ATTLIST ingredient quantity CDATA #REQUIRED>
这里设置属性类型。CDATA代表字符数据。意味着处理器在属性内可以得到文本。
<!ATTLIST ingredient quantity CDATA #REQUIRED>
最后的部分定义属性的缺省值。可以使用实际的数值,如3。这样,XML中空白长度的属性值将为3。输入的值将覆盖缺省值。
在上面的例子中我没有设置特定的数量,而是使用XML的关键字#REQUIRED。它告诉处理器次属性必须包含一个值。如果空白,文档将不被处理。
缺省值有另外两个关键字。第一个是#FIXED - 如果属性值在整个文档中保持相同的值。假设我定义一个p_w_picpath的标记符属性,所有图像的大小都相同,比如说100*50像素,就可以在DTD中这样定义属性:
<!ATTLIST picture length CDATA #FIXED "100 px">
<!ATTLIST picture width CDATA #FIXED "50 px">
另一个关键字是#IMPLIED,表示属性可以包含值或是空的。
下面让我们看看属性类型。
如果你决定自己写DTD,可能需要一本解释ATTLIST语句中所有组合的XML的书。但是如果借用DTD,或许只知道CDATA和另外三种属性就性了。
第一个是ID。它要求属性的值在文档中不重复。使用过数据库的人都知道唯一标志符的必要性。DTD ATTLIST语句看起来象这样:
<!ATTLIST element_name attribute_name ID #REQUIRED>
很难想象没有#REQUIRED缺省值的ID属性类型。如果那样,任何重复的或空的ID都会迫使处理器返回一个错误。ID必须以字母或下划线开始并且不能包含任何空格。
NMTOKEN类型也使用上面的命名规则。但是允许重复。它被用做传递数据给应用程序的保障。大多数程序语言,包括Java和JavaScript,在模块名中不能有空格。大多数情况下,最好保证属性符合它们的规则。
最后是枚举类型,不需要特定的关键字。而是用"|"符号包含在括号内的值,例如:
<!ATTLIST sibling (brother | sister) #REQUIRED>
如果有有限的可能的属性值,可以用这种方式。
实体
有五种预定义的XML实体,HTML编码者应该熟悉。XML文档中的字符&、<、>、"和'被分别表示为&、@lt;、>、"和'。
XML很大程度上扩展了实体的功能 - 允许在DTD中定义实体以便在文档的其余部分使用。例如,我在XML文档中需要频繁使用词组"Wired Digital",可以在DTD中这样表示:
<!ENTITY wd "Wired Digital">
这样当我使用这个词组时,可以敲入&wd;。于是可以避免拼错和重复敲入相同的信息。实体可以起到字处理器中宏的作用。
被替换的文本可以任意长,但是如果真是很长,可能要把信息存储在另一个文件中。可以通过外部实体参考来实现 - 在实体名和文件的URL中使用关键字SYSTEM:
<!ENTITY text SYSTEM "
http://my.url.here">
这些特征功能强大,但有一个缺点:在一个DTD内不能被扩展。为了实现扩展功能,需要一个称为参数实体的特殊工具。它在实体定义中通过在实体名前插入"%"实现。一旦被定义,参数定义可以通过用百分号和分号包围参数名来实现。
为什么这么做?看看下面的代码:
<!ELEMENT vCard (%prop.man;, (%prop.id; | %prop.del; |
%prop.tel; | %prop.geo; | %prop.org; |
%prop.exp; | %prop.sec;)*)>
这段代码来自一个公用的XML名片草稿。当定义根元素时,作者发现更容易把信息分离到不同的参数实体中。如果看看其中的一个实体表现,我们就会知道为什么了。看看下面的prop.id实体: <!ENTITY % prop.id "
(nickname | photo | bday)">
如果每个实体都用这么长的字符串表示,元素定义将很难阅读。
现在可以读一些DTD了。
Jay Greenspan ISO-8859-1 Entities
Named Entity Numeric Entity Glyph Description �- unused horizontaltab linefeed unused space ! ! exclamationmark " " " doublequotationmark # # numbersign $ $ dollarsign % % percentsign & & & amperstand ' ' apostrophe ( ( leftparenthesis ) ) rightparenthesis * * asterisk + + plussign , , comma - - hyphen . . period(fullstop)
Named
Entity Numeric Entity Glyph Description
/ / solidus(slash)
0- 9 digits0-9 : : colon ; ; semicolon < < < less-thansign = = equalssign > > > greater-thansign ? ? questionmark @ @ commercialat A- Z letters A-Z [ ][ leftsquarebracket \ \ reversesolidus(backslash) ] ] rightsquarebracket ^ ^ caret _ _ horizontalbar(underscore) ` ` acuteaccent a- z letters a-z { { leftcurlybrace | | verticalbar
Named
Entity Numeric Entity Glyph Description } } rightcurlybrace ~ ~ tilde - Ÿ unused non-breakingspace ¡ ¡ invertedexclamation ¢ ¢ centsign £ £ poundsterling ¤ ¤ generalcurrencysign ¥ ¥ yensign ¦ ¦ brokenverticalbar § § sectionsign ¨ ¨ umlaut(dieresis) © © © copyright ª ª feminineordinal « « leftanglequote, guillemotleft ¬ ¬ notsign softhyphen ® ® registeredtrademark ¯ ¯ macronaccent
Named
Entity Numeric Entity Glyph Description ° ° degreesign ± ± plusorminus ² ² superscripttwo ³ ³ superscriptthree ´ ´ acuteaccent µ µ microsign ¶ ¶ paragraphsign · · middledot ¸ ¸ cedilla ¹ ¹ superscriptone º º masculineordinal » » rightanglequote, guillemotright ¼ ¼ one-fourth ½ ½ one-half ¾ ¾ three-fourths ¿ ¿ invertedquestionmark À À À uppercaseA, graveaccent Á Á Á uppercaseA, acuteaccent    uppercaseA, circumflexaccent
Named
Entity Numeric Entity Glyph Description à à à uppercaseA, tilde Ä Ä Ä uppercaseA, dieresisorumlautmark Å Å Å uppercaseA, ring Æ Æ Æ uppercaseAEdipthong(ligature) Ç Ç Ç uppercaseC, cedilla È È È uppercaseE, graveaccent É É É uppercaseE, acuteaccent Ê Ê Ê uppercaseE, circumflexaccent Ë Ë Ë uppercaseE, dieresisorumlautmark Ì Ì Ì uppercaseI, graveaccent Í Í Í uppercaseI, acuteaccent Î Î Î uppercaseI, circumflexaccent Ï Ï Ï uppercaseI, dieresisorumlautmark Ð Ð Ð uppercaseEth, Icelandic Ñ Ñ Ñ uppercaseN, tilde Ò Ò Ò uppercaseO, graveaccent Ó Ó Ó uppercaseO, acuteaccent Ô Ô Ô uppercaseO, circumflexaccent Õ Õ Õ uppercaseO, tilde
Named
Entity Numeric Entity Glyph Description Ö Ö Ö uppercaseO, dieresisorumlautmark × × multiplysign Ø Ø Ø uppercaseO, slash Ù Ù Ù uppercaseU, graveaccent Ú Ú Ú uppercaseU, acuteaccent Û Û Û uppercaseU, circumflexaccent Ü Ü Ü uppercaseU, dieresisorumlautmark Ý Ý Ý uppercaseY, acuteaccent Þ Þ Þ uppercaseTHORN, Icelandic ß ß ß lowercasesharps, German(szligature) à à à lowercasea, graveaccent á á á lowercasea, acuteaccent â â â lowercasea, circumflexaccent ã ã ã lowercasea, tilde ä ä ä lowercasea, dieresisorumlautmark å å å lowercasea, ring æ æ æ lowercaseaedipthong(ligature) ç ç ç lowercasec, cedilla è è è lowercasee, graveaccent
Named
Entity Numeric Entity Glyph Description é é é lowercasee, acuteaccent ê ê ê lowercasee, circumflexaccent ë ë ë lowercasee, dieresisorumlautmark ì ì ì lowercasei, graveaccent í í í lowercasei, acuteaccent î î î lowercasei, circumflexaccent ï ï ï lowercasei, dieresisorumlautmark ð ð ð lowercaseeth, Icelandic ñ ñ ñ lowercasen, tilde ò ò ò lowercaseo, graveaccent ó ó ó lowercaseo, acuteaccent ô ô ô lowercaseo, circumflexaccent õ õ õ lowercaseo, tilde ö ö ö lowercaseo, dieresisorumlautmark ÷ ÷ divisionsign ø ø ø lowercaseo, slash ù ù ù lowercaseu, graveaccent ú ú ú lowercaseu, acuteaccent û û û lowercaseu, circumflexaccent
Named
Entity Numeric Entity Glyph Description ü ü ü lowercaseu, dieresisorumlautmark ý ý ý lowercasey, acuteaccent þ þ þ lowercasethorn, Icelandic ÿ ÿ ÿ lowercasey, dieresisorumlautmark |
转载于:https://blog.51cto.com/youxue/345324