新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   >>中国XML论坛<<     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 关于 XML 的一般性技术讨论,提供 XML入门资料 和 XML教程
    [返回] 中文XML论坛 - 专业的XML技术讨论区XML.ORG.CN讨论区 - XML技术『 XML基础 』 → XML 规范化形式简介 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 11588 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: XML 规范化形式简介 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     anchen0617 帅哥哟,离线,有人找我吗?双子座1983-6-17
      
      
      威望:5
      等级:大二(研究C++)
      文章:281
      积分:3413
      门派:XML.ORG.CN
      注册:2004/10/17

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给anchen0617发送一个短消息 把anchen0617加入好友 查看anchen0617的个人资料 搜索anchen0617在『 XML基础 』的所有贴子 访问anchen0617的主页 引用回复这个贴子 回复这个贴子 查看anchen0617的博客楼主
    发贴心情 XML 规范化形式简介

    XML 的传统来自文档世界,这在其语法规则中也得到反映。与数据库记录的数据格式相比,它的语法更加宽松。XML 解析器将 XML 文档的编码形式(编码在 XML 声明中规定)转化成表示 XML 文档信息的抽象模型。W3C 将这种抽象模型形式化为 XML Infoset(请参阅参考资料),但是许多 XML 处理必须考虑已编码的源代码形式,这种形式允许存在多种不同的词法格式:属性的顺序没有规定,元素名及其属性间的空白字符的使用规则也很灵活,并且有多种不同的表示字符和转义特殊字符的方法等。名称空间又带来了更大的词法灵活性(比如是否使用前缀是可选的)。结果造成您拥有许多按照 XML 1.0 规则完全等价的文档,但在对编码的源文件进行逐字节比较时,它们可能完全不同。

    词法上的灵活性在诸如回归测试和数字签名等方面带来了一些问题。假设要创建一个包含案例的测试集,想以清单 1 中的文档作为正确的输出结果。

    清单 1. 示例 XML 文档

    <doc>
      <a a1="1" a2="2">123</a>
    </doc>
      

    如果要进行严格意义上的 XML 测试,那么您应该认识到,应该将清单 2 中的文档也看作是一个正确的输出。

    清单 2. 清单 1 中 XML 文档的等价形式

    <?xml version="1.0" encoding="UTF-8"?>
    <doc>
      <a
         a2="2"   a1="1"
      >123</a>
    </doc>
      

    标签之内的空白不同,属性的顺序也改变了,而且字符实体被换成了等价的文字字符,但毫无疑问的是,Infoset 是完全相同的。通过逐字节的比较来建立这种等同性是很难的。如果希望保证通过消息系统发送的文档在传递过程中没有被破坏或篡改,那么就要用到数字签名。为此,需要使用加密的散列值或者完善的文档数字签名。但是,如果通过消息系统发送清单 1,经过常规的处理之后,清单 1 有可能变成 清单 2。这样的话,简单的散列值或者数据签名就无法匹配,尽管文档实质上并没有被修改。

    解决这一问题的 W3C 解决方案已经作为 XML 数字签名规范的一部分开发出来了。W3C 定义了规范化 XML(请参阅参考资料),这是 XML 的规范化词法形式,去掉了所有允许的变化,采用了严格的规则来进行逐字节比较。转化成规范形式的过程称为规范化(通常缩写为“c14n”)。本文将介绍 XML 规范形式。

    规范化形式规则
    c14n 过程的最佳概括就是规范中提供的列表(我做了一些修改),如下所示:

    文档用 UTF-8 编码。
    解析之前输入中的断行规范化为“#xA”。
    像验证解析器那样将属性值规范化。
    像验证解析器那样向元素中添加默认属性。
    将 CDATA 节替换为它们的文字字符内容。
    字符和已解析实体引用替换为文字字符(特殊字符除外)。
    属性值和字符内容中的特殊字符替换为字符引用(与一般的结构良好的 XML 相同)。
    删除 XML 声明和 DTD。(注意:通常我建议使用 XML 声明,但是赞同在规范化 XML 形式中忽略 XML 声明的理由。)
    将空的元素转化成起始-结束标签对。
    规范化文档元素之外和起始、结束标签之间的空白。
    保留字符内容中的所有空白(不包括换行规范化过程中删除的字符)。
    属性值分隔符设为引号(双引号)。
    删除各元素中多余的名称空间声明。
    对名称空间声明和每个元素中的属性采用词典序。
    不必担心这些规则是否有点不清楚,后面还将详细地解释,并通过例子说明实际应用的更一般的规则。本文中不讨论 c14n 步骤中涉及到 DTD 验证的部分。我曾经多次提到 XML Infoset,但有意思的是 W3C 没有选择在 Infoset 的基础上定义 c14n,而是按照 XPath 数据模型(一种比 Infoset 更简单的数据模型,有人说该模型更清晰)来定义 c14n。这可能是个无关轻重的细节,不会影响您对规范化形式的理解,但是如果需要使用基于 Infoset 的技术,则有必要记住这一点。

    规范化标签
    标签规范化需要在标签中应用特定的空白规则、特定顺序的名称空间声明和规整的属性。下面是我自己总结的建立规范化起始标签的非正式的步骤:

    左尖括号(<),后面跟着元素 QName(前缀加冒号和本地名)。
    如果有默认名称空间声明的话紧跟在后面,然后是其他名称空间声明,按照定义前缀的字母顺序。省略所有多余的名称空间声明(已经在祖先元素中声明而且没有被改写的名称空间)。每个名称空间声明之间有一个空格,等号和包含名称空间的 URI 两侧没有空格。
    所有的属性按照字母顺序排列,前面有一个空格,等号、包含属性值的双引号两侧没有空格。
    最后是右尖括号(>)。
    规范形式的结束标签很简单:左尖括号(<)、元素 QName 和右尖括号(>)。清单 3 是一个非规范形式的 XML 例子。

    清单 3. 非规范形式的 XML 的例子
    <?xml version="1.0" encoding="UTF-8"?>
    <doc xmlns:x="http://example.com/x" xmlns="http://example.com/default">
      <a
         a2="2"   a1="1"
      >123</a>
      <b y:a1='1' xmlns="http://example.com/default" a3='"3"'
         xmlns:y='http://example.com/y' y:a2='2'/>
    </doc>
      

    清单 4 是同一文档的规范形式。

    清单 4. 清单 3 的规范形式

    <doc xmlns="http://example.com/default" xmlns:x="http://example.com/x">
      <a a1="1" a2="2">123</a>
      <b xmlns:y="http://example.com/y" a3="&quot;3&quot;" y:a1="1" y:a2="2"></b>
    </doc>
      

    规范化清单 3 需要做以下修改:

    删除 XML 声明(文档已经采用 UTF-8 编码,不需要转换)。
    将 doc 上的默认名称空间声明放在其他名称空间(该例中前缀为 x 的名称空间)的前面。
    减少 a 起始标签中的空格,每个属性之前只留下一个空格。
    删除 b 起始标签中多余的默认名称空间声明。
    确保其余的名称空间声明(对于 y 前缀)出现在其他所有属性的前面。
    其他属性按照它们的 QNames(如“a3”、“y:a1”、“y:a2”)以字母顺序排列。
    将 xmlns:y 名称空间声明、属性 y:a1、y:a2 和 a3 上的分隔符从单引号(')改为双引号("),a3 还需要将嵌套的双引号(")转义成 &quot;。
    我使用了 Python c14n 模块测试规范形式的转换,该模块来自 PyXML (请参阅参考资料)。清单 5 是用来将 清单 3 规范化成 清单 4 的代码。

    清单 5. 规范化 XML 的 Python 代码
    from xml.dom import minidom
    from xml.dom.ext import c14n
    doc = minidom.parse('listing3.xml')
    canonical_xml = c14n.Canonicalize(doc)
    print canonical_xml

    规范化字符数据
    规范形式的字符数据基本上就是尽量使用文字:字符实体被解析为原始的 Unicode(然后序列化为 UTF-8);CDATA 区段则用原来的内容替换;沿着这条路进行其他的替换。这种方法同样适用于属性值和内容中的字符数据。还将按照 DTD 类型规则规范化属性,但这主要与使用 DTD 的文档有关,本文不再讨论。清单 6 中的示例文档部分参考了 c14n 规范中的一个例子。

    清单 6. 字符数据规范化的 XML 例子
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <doc>
       <text>First line Second line</text>
       <value>2</value>
       <compute><![CDATA[value>"0" && value<"10" ?"valid":"error"]]></compute>
       <compute expr='value>"0" &amp;&amp; value&lt;"10" ?"valid":"error"'>valid</compute>
    </doc>

    清单 7 是规范形式的同一文档。

    规范化清单 6 需要做以下修改:

    删除 XML 声明并转化为 UTF-8 形式。
    将字符引用 2 改为实际的数字 2。
    CDATA 节替换为内容,并使用 &gt; 转义右尖括号(>),用 &amp; 转义“与”符号(&),用 &lt; 转义右尖括号(<)。
    用双引号代替 expr 属性中所用的单引号,然后将双引号(")字符转义成 &quot;。
    清单 6 和清单 7 都没有涉及到的一个重要步骤是到 UTF-8 的转化,因为这不方便用清单来说明。假设源文档内容中包含字符引用 ©(表示版权符号),规范形式将使用 UTF-8 序列来代替(十六进制字节 C2 和 A9)。

    结束语
    有时候真正需要的可能是签署或比较 XML 文档的一个子树,而不是全部内容。可能您只想签署 SOAP 消息主体而忽略信封。W3C 在 专用规范形式的规范中提供了这种机制,它基本上是对目标子树内外的名称空间声明进行排序。

    我提到了前缀选择造成的各种可能的变化。XML Namespaces 规定前缀是无关紧要的,因此只有名称空间前缀不同的两个文件应视作同一文件。不幸的是,c14n 没有考虑这种情况。某些完全合法的 XML 处理操作可能修改前缀,因此要注意这类潜在的问题。

    Canonical XML 是一个需要牢牢掌握的重要工具。您可能不会马上遇到与 XML 有关的安全或软件测试问题,但是一旦熟悉这些领域您会奇怪为何经常需要 c14n。它是帮助您清除最初没有注意避免的潜在问题的工具之一。


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    xml这门语言太好了,我们共同努力吧!!!!!

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/1/15 10:16:00
     
     BaSaRa 帅哥哟,离线,有人找我吗?
      
      
      等级:大二期末(汇编考了97分!)
      文章:28
      积分:352
      门派:XML.ORG.CN
      注册:2005/1/14

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给BaSaRa发送一个短消息 把BaSaRa加入好友 查看BaSaRa的个人资料 搜索BaSaRa在『 XML基础 』的所有贴子 引用回复这个贴子 回复这个贴子 查看BaSaRa的博客2
    发贴心情 
    不错,基础的东西很多

    ----------------------------------------------
    XML Chobo - -!

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/1/15 12:50:00
     
     xssh 美女呀,离线,快来找我吧!
      
      
      等级:大一(高数修炼中)
      文章:17
      积分:129
      门派:XML.ORG.CN
      注册:2005/1/10

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给xssh发送一个短消息 把xssh加入好友 查看xssh的个人资料 搜索xssh在『 XML基础 』的所有贴子 引用回复这个贴子 回复这个贴子 查看xssh的博客3
    发贴心情 
    收藏。谢了
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/1/19 21:01:00
     
     sunrisefe 美女呀,离线,快来找我吧!
      
      
      等级:大二(研究汇编)
      文章:63
      积分:271
      门派:GOOGLEBBS.NET
      注册:2004/9/2

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给sunrisefe发送一个短消息 把sunrisefe加入好友 查看sunrisefe的个人资料 搜索sunrisefe在『 XML基础 』的所有贴子 点击这里发送电邮给sunrisefe  引用回复这个贴子 回复这个贴子 查看sunrisefe的博客4
    发贴心情 
    SAVE

    ----------------------------------------------
    A man who has the knowledge but lacks the power to clearly express himself is no better off than if he had never any idea at all.

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2006/4/26 16:46:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 XML基础 』的所有贴子 点击这里发送电邮给Google AdSense  访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2025/6/21 18:02:34

    本主题贴数4,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    78.125ms