相关文章推荐
没读研的大葱  ·  TYPE_NAME ...·  2 月前    · 
机灵的鸵鸟  ·  Spring ...·  1 年前    · 

许多开发人员在 XHTML 中使用实体代替特殊字符,但是也可以在 XML 中定义实体来简化创作或者引用外部文档的内容。在我们创建文档类型定义(Document Type Definition,DTD)并试图减小它的表面复杂性以便适合人类阅读时,实体也能派上用场。本文将全面介绍 XML 实体,并展示如何在文档中利用它们的优势。

Chris Herborth , 技术作家兼软件开发人员, Freelance

2010 年 4 月 01 日

常用缩写词

  • ASCII:美国信息交换标准码
  • DOM:文档对象模型
  • DTD:文档类型定义
  • HTML:超文本标记语言
  • W3C:万维网联盟
  • XHTML:可扩展超文本标记语言
  • XML:可扩展标记语言

XML 是一种受到良好支持的 Internet 标准,用于以一种特殊方式编码结构化数据:XML 编码的数据几乎能够用所有编程语言轻松解码,甚至可以使用标准文本编辑器由人类阅读或编写。许多应用程序,特别是遵循现代标准的 Web 浏览器,都可以直接处理 XML 数据。

XML 中的实体用于表示特殊字符(通常难以或不可能在标准键盘上输入),重用 XML 代码段,将文档组织为几个文件,以及简化 DTD 的编写。

什么是实体?

实体是对数据的引用;根据实体种类的不同,XML 解析器将使用实体的替代文本或者外部文档的内容来替代实体引用。本文中要介绍以下几种实体,了解它们的工作方式,以及如何在我们自己的 XML 文档中利用它们的优势。

  • 字符实体
  • 命名实体
  • 外部实体
  • 参数实体

所有实体(除参数实体外)都以一个与字符(&)开始,以一个分号(;)结束。XML 标准定义了所有 XML 解析器都必须实现的 5 种标准实体,尽管它们还支持其他实体。

  • ' 是一个撇号:'
  • & 是一个与字符:&
  • " 是一个引号:"
  • &lt; 是一个小于号:<
  • &gt; 是一个大于号:>

我们经常会在 XHTML 和 XML 文档中看到和用到 &amp;、&lt; 和 &gt; 实体,特别是那些通过展示示例来归档标记的文档。

对于字符实体,我们可以用十进制格式(&# nnn ;,其中 nnn 是字符的十进制值)或十六进制格式(&#x hhh ;,其中 hhh 是字符的十六进制值)来指定任意 Unicode 字符。

例如,大写字母 A 是 Unicode 字符 U+0065。如果想将其表示为一个字符实体,可以输入 &#65;(十进制值)或 &#x41;(十六进制值)。另一个更有用的字符也许是 © —— 版权符号。这个版权符号的字符实体是 &#169; 或 &#xa9;,因为它是 Unicode 字符 U+0169。

在进行其他实体相关的解析之前,将首先替代字符实体。对 XML 解析器而言,字符实体与直接输入指定字符的效果完全相同。字符实体类似于 C 编程语言中的三联符(trigraphs):只是特定字符的替代表示。

还应该注意到,尽管 XML 解析器可以毫不费力地处理 “任何” 字符实体,但这些字符实体可能对处理应用程序和显示系统毫无益处。确保能够访问适当的字体和编码支持系统,以便在文档中显示任何稀奇古怪的字符。当前字体中找不到某个适当的字符时,多数系统会显示一个某种占位符。

命名实体(在 XML 规范中也称为内部实体)就是我们在谈论 “实体” 时所指的实体。命名实体在 DTD 或内部子集(即文档中 <!DOCTYPE> 语句的一部分)中声明,在文档中用作引用。在 XML 文档解析过程中,实体引用将由它的表示替代。

简单来说,实体就是宏,它们在我们处理文档时得到扩展。

XHTML 规范使用命名实体来表示 ISO 8859-1 (Latin 1) 字符集中包含的、但在多数键盘上没有的特殊字符。其他实体用于指定特殊字符和符号。这些标准实体受到 Web 浏览器的良好支持,甚至允许我们在只支持 7 位 ASCII 字符集的系统(是的,还有人在使用古老的大型机系统)上使用纯文本编辑器来编写 XHTML 文档。 清单 1 提供了 XHTML 1.0 的特殊字符的简要列表。

清单 1. XHTML 1.0 的几个特殊字符
<!ENTITY ndash   "&#8211;"> <!-- en dash, U+2013 ISOpub -->
<!ENTITY mdash   "&#8212;"> <!-- em dash, U+2014 ISOpub -->
<!ENTITY lsquo   "&#8216;"> <!-- left single quotation mark,
                                    U+2018 ISOnum -->
<!ENTITY rsquo   "&#8217;"> <!-- right single quotation mark,
                                    U+2019 ISOnum -->
<!ENTITY sbquo   "&#8218;"> <!-- single low-9 quotation mark, 
                                    U+201A NEW -->
<!ENTITY ldquo   "amp;“"> <!-- left double quotation mark,
                                    U+201C ISOnum -->
<!ENTITY rdquo   "&#8221;"> <!-- right double quotation mark,
                                    U+201D ISOnum -->

清单 1 (它是一块 XHTML 1.0 Special Characters 声明)所示,命名实体由字符实体替代。如 上一小节 所述,字符实体等同于在文档中直接输入的引用字符。

我们在文档中使用 &ndash; 时,它由 Unicode 字符 U+2013(短横线 - 字符)替代。由于 &ndash; 的替代文本是一个字符引用,因此它等同于输入一个短横线字符。

命名实体在整个文档被读取后进行解析。这样,一些命名实体完全可以引用其他命名实体,其原因是所有实体都将在它们被扩展之前声明。例如, 清单 2 展示了两个实体,其中一个实体引用另一个实体。

清单 2. 引用实体的实体
<!ENTITY c "Chris">
<!ENTITY ch "&c; Herborth">

在一个文档中使用 &c; 将扩展为 Chris,&ch; 将扩展为完整的 Chris Herborth。

循环引用是实体中的错误。因创建了循环引用而使文档无效时,解析器会报告错误。

使用 Firefox、Safari 和 Chrome 时,这些实体引用的效果与在存储为 XML 文件的 XHTML 文档中的效果一样,但使用 Microsoft® Internet Explorer® 8 时效果不一样。我将在 在文档中定义实体 小节中介绍如何声明命名实体。

外部实体表示外部文件的内容。外部实体在有些情况下很有用,比如说,您在创建一本图书并且想将每一章存储为一个单独的文件。您可能会创建一组如 清单 3 所示的实体。

清单 3. 外部实体引用其他文件
<!ENTITY chap1 SYSTEM "chapter-1.xml">
<!ENTITY chap2 SYSTEM "chapter-2.xml">
<!ENTITY chap3 SYSTEM "chapter-3.xml">

现在,当您在主图书 XML 文件(参见 清单 4 )中将这些实体放到一起时,这些文件的内容将插入在引用点。

清单 4. 将各章放到一起
<?xml version="1.0" encoding="utf-8"?>
<!-- Pull in the chapter content: -->
&chap1;
&chap2;
&chap3;

由于这些文件的内容被插入到 XML 文档中,因此它们也必须是有效的 XML,而且它们必须是平衡的。也就是说,在一个外部实体的引用文件中开始的任何元素也必须在那个文件中结束。当 清单 4 中的 XML 文档被解析时,它将被读取为一个大文档,包含 chapter-1.xml、chapter-2.xml 和 chapter-3.xml 文件的内容;XML 处理应用程序并不介意文档写入到 4 个单独的文件中。

参数实体只用于 DTD 和文档的内部子集中。它们使用百分号(%)而不是与字符,可以是命名实体或外部实体。

在 XHTML DTD 中,参数实体用于引用在外部文件中声明的 Latin 1, Special Characters and Symbols 实体集,以及用作快捷方式以重用 DTD 的某些部分,比如每个 XHTML 元素都支持的标准属性集(参见 清单 5 )。

清单 5. XHTML 1 DTD 中的一个参数实体
<!ENTITY % attrs "%coreattrs; %i18n; %events;">
<!ENTITY % coreattrs
 "id          ID             #IMPLIED
  class       CDATA          #IMPLIED
  style       %StyleSheet;   #IMPLIED
  title       %Text;         #IMPLIED"
<!ENTITY % i18n
 "lang        %LanguageCode; #IMPLIED
  xml:lang    %LanguageCode; #IMPLIED
  dir         (ltr|rtl)      #IMPLIED"
      

如 清单 5 所示,参数实体可以引用其他参数实体。与命名实体一样,参数实体在整个文档被读取之后才被扩展。

在文档中定义实体

您也许已经注意到,实体使用 ENTITY 声明进行定义,既可以作为外部 DTD 的一部分(参见 清单 6),也可以作为文档的外部子集的一部分(参见 清单 7)。

清单 6. DTD 中的实体声明
<!-- 6.1 Named entity for site name: -->
<!ENTITY dw "developerWorks">
<!-- 6.2 External entity for re-use: -->
<!ENTITY bio SYSTEM "dw-author-bio.xml">
<!-- 6.3 Parameter entity for use in DTD -->
<!ENTITY % English "en-US|en-CA|en-UK">

在声明命名实体时,指定实体的名称及其替代文本。替代文本可以包含字符实体、命名实体和元素等,但不包含参数实体。

清单 7. 内部子集中的实体声明
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html 
    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
    <!ENTITY test-entity "This <em>is</em> an entity.">
<html xmlns="http://www.w3.org/1999/xhtml">
    <meta http-equiv="Content-Type" content="application/xhtml+xml;charset=utf-8"/>
    <title>Entities in XML</title>
</head>
    <h1>Entities in XML</h1>
    <p>&test-entity;</p>
    <p>You can use it anywhere you'd use a standard XHTML entity:</p>
    <pre>&test-entity;</pre>
</body>
</html>

清单 7 中的 XHTML 文档(在我的系统上保存为 entities.xml)在其内部子集中声明了一个名为 test-entity 的新实体。内部子集是 <!DOCTYPE> 声明的一部分,位于 DTD 的 PUBLIC 和/或 SYSTEM 标识符之后的方括号中。

浏览器目前似乎不支持内部子集中的外部实体或参数实体,这也许是一个安全措施。当这两种类型的实体与 Web 浏览器的呈现引擎一起使用时,可能被用于创建拒绝服务攻击或其他恶意文档。

在文档中使用实体

现在已经熟悉在文档中使用实体的机制;DTD 中的参数实体的工作方式与此相同。前面所示的清单展示了如何使用各种实体:

在需要反复输入相同的文本时,可以尝试利用实体。以下是一些不错的实体示例:公司的正式名称、正在进行文档记录的产品的名称、版权、商标、注册商标通知,以及电子邮件地址(参见 清单 8)。

清单 8. 通过实体减少输入
<!ENTITY co "Father Karass' Olde Tyme Steambots, LLC">
<!ENTITY prod "Semi-Autonomous Security Servant (SASSbot)">
<!ENTITY author "Chris Herborth (chrish@pobox.com)">

可能变化的事物(比如产品名称)非常适合使用实体,这与在程序源代码中声明常量很相似。当产品名称变化时,我们只需更新实体声明,不必搜索并替代所有文件(参见 清单 9)。

清单 9. 使用实体轻松更新不断变化的文档
<!-- Current name: -->
<!ENTITY prod "Semi-Autonomous Security Servant (SASSbot)">
<!-- Old names preserved for posterity: -->
<!-- Original R&D name: -->
<!--ENTITY prod "Security Bot"-->
<!-- Marketing name v1 -->
<!--ENTITY prod "Security Servant Bot"-->
<!-- Marketing name v2 -->
<!--ENTITY prod "Autonomous Security Servant Bot"-->

基于 XML 的标准(比如 XHTML)定义了一个有用的实体库,这使得创建包含不能在标准键盘上直接输入的字符的文档成为可能。命名实体的作用类似于宏,允许您使用实体引用替代重复或难以输入的文本。尽管 Web 浏览器不支持外部实体,但是我们可以通过其他 XML 应用程序来使用它们创建复合文档,这使得标准化和重用文档的某些部分变得更容易。参数实体用于将外部声明拖到 DTD 中,或者用于创建 DTD 内部宏来改善可读性。

在 XML 文档的 DOCTYPE 声明中声明命名实体很简单,而且您可能已经知道如何在文档主体中使用它们。

转载自:http://www.ibm.com/developerworks/cn/xml/x-entities/

为文档创建文本宏许多开发人员在 XHTML 中使用实体代替特殊字符,但是也可以在 XML 中定义实体来简化创作或者引用外部文档的内容。在我们创建文档类型定义(Document Type Definition,DTD)并试图减小它的表面复杂性以便适合人类阅读时,实体也能派上用场。本文将全面介绍 XML 实体,并展示如何在文档中利用它们的优势。0 评论:Ch
实体可以简单的理解为引用数据项的方法,可以是普通的文本也可以是二进制数据。     实体可以分为通用实体和参数实体。通用实体用于XML,用于引用文本或者二进制数据,而参数实体只能在DTD使用。通用实体与参数实体可以是内部实 体或者是外部实体实体还可以分为未解析与解析的实体,不同在于解析实体是规范的XML文本,而未解析的实体是不应该被解析器解析的二进制数据。 3种实体可以组合出8种实体,...
实体就是来代替字符数据的,它可以减少大量工作 ,一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;). 实体是用于定义引用普通文本或特殊字符的快捷方式的变量。 实体引用是对实体的引用。 实体可在内部或外部进行声明。 普通实体在dtd定义,在XML文档使用,分为内部与外部实体,外部实体就是引用其他的XML文件的内容来作为一个实体(要是直接...
2012-08-07 1、XML实体可分为普通内部外部实体和内部外部参数实体。普通内部外部实体用在XML文档,而内部外部参数实体用在DTD声明。 2、DTD声明普通内部实体语法:,调用时用格式“&实体名;”。 3、DTD声明普通外部实体语法:,表示使用URI或者URL指向文件的全部内容替换实体名,比较少用,调用时用格式“&实体名;”。 4、DTD声明内部参数实体语法:,
目录一、什么是XML外部实体注入?二、XXE漏洞如何产生?什么是XML?什么是XML实体?什么是文件类型定义(DTD)?什么是XML自定义实体?什么是XML外部实体?三、XXE攻击有哪些类型?利用XXE检索文件利用XXE执行SSRF攻击四、寻找用于XXE注入的隐藏攻击面XInclude攻击通过文件上传进行XXE攻击通过修改的内容类型进行XXE攻击五、如何预防XXE漏洞 一、什么是XML外部实体注入? XML外部实体注入(也称为XXE)是一个Web安全漏洞,它使攻击者能够干扰应用程序对XML数据的处理。它通
发现里面还有个dologin.php类似于PHP源码。所以我们考虑BP抓包发现是个XXE漏洞Accept: application/xml, text/xml, */*; q=0.01 X-Requested-With: XMLHttpRequest 我们用这个格式payl 2. XXE是怎么发生的? XML规范包含了一些不安全的特性,如果XML parser实现了这些特性,就存在安全隐患。XML external entity是一种自定义XML实体,其定义的值是从声明它们的DTD外部加载的。从安全性的角度来看,外部实体会存在潜在风险,因为它们允许根据文件路径或URL的内容定义实体。 3. XXE攻击的种类 3.1 利用XXE读取文件内容 为了实现这种攻击,有两种方式: