[译]EPUB Canonical Fragment Identifier (epubcfi) Specificationhtml
[注]因为做者本文水平有限,加之英文理解有限,本文翻译旨在学习EPUB CFI规范,经过本文看快速了解CFI标记方法和理解CFI在EPUB出版物中的做用。git
EPUB CFI规范经过在EPUB出版物中使用片断标识定义引用到任意内容的标准化方法。架构
网页已经证实了超连接的概念是及其强大的,然而,EPUB出版物已经否认了超连接可能带来的好处,应为它缺少一个连接到内容的标准机制。尽管一些私有化的机制已经被一些阅读系统开发并实现,然而他们没有一个好理解的语法,而且没有达到跨平台的互操做性。打破互操做性障碍从功能性来看是意义重大的,而且,该规范作出一些改变:从阅读位置维护一个标注用于导航,并指向任何出版物的能力打开了一个新的维度,不只仅像超连接那样只有做者或开发人员才能够添加。app
EPUB CFI规范定义一个能惟一识别在出版物中的任何位置或简单范围的结构化引用试图纠正目前的状态。下面一些考虑强烈的影响了该规范的设计和范围:ide
在文档中使用的EPUB规范术语请参考EPUB规范。svg
出版级别的EPUB CFI连接到一个EPUB出版物。EPUB CFI的路径引用到出版物的位置。函数
一个内部的EPUB CFI出版物容许一个内容文档引用到出版物内部另一个文档。这个EPUB CFI路径引用到当前出版物文档包。学习
详情请参考内部出版物的CFI。测试
片断标识符是IRI[RFC3987]规范的一部分,定义了资源中的位置。语义上,它是一个以井号(#)开始并附到IRI资源尾部的片断。对HTML文档而言,ID和命名的锚被做为片断标识符,在XML中,缩写的的XPointer[XPTRSH]标识被用来引用到给定的ID。flex
标准片断标识符(CFI)是一个相似的结构,它用来表示一个EPUB出版物中的一个位置信息。例如:
book.epub#epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/3:10)
跟在井号(#)后面的函数式字符串表示了符合本文档规范的片断标识符,而且,包含在括号中的值是一个用于引用到规范出版物(book.epub)中的一个片断位置。使用在路径解析一节中定义的处理规则,任何阅读系统能够解析这些语法,打开对应出版物的内容文档,并为用户定位到指定位置。
一个完整的EPUB CFI语法定义在下一节中阐述。
(EBNF productions ISO/IEC 14977)
fragment = "epubcfi(" , ( path | range ) , ")" ; path = step , local_path ; range = path , "," , local_path , "," , local_path ; local_path = { step | "!" } , [ termstep ] ; step = "/" , integer , [ "[" , assertion , "]" ] ; termstep = terminus , [ "[" , assertion , "]" ] ; terminus = ( ":" , integer ) | ( "@" , number , ":" , number ) | ( "~" , number ) | ( "~" , number , "@" , number , ":" , number ) ; number = ( digit-non-zero , { digit } , [ "." , { digit } , digit-non-zero ] ) | ( zero , "." , { digit } , digit-non-zero ) ; integer = zero | ( digit-non-zero , { digit } ) ; assertion = [ csv ] , { parameter } ; parameter = ";" , value-no-space , "=" , csv ; csv = value , { "," , value } ; value = string-escaped-special-chars ; value-no-space = value - ( [ value ] , space , [ value ] ) ; special-chars = circumflex | square-brackets | parentheses | comma | semicolon | equal ; escaped-special-chars = ( circumflex , circumflex ) | ( circumflex , square-brackets ) | ( circumflex , parentheses ) | ( circumflex , comma ) | ( circumflex , semicolon ) | ( circumflex , equal ) ; character-escaped-special = ( character - special-chars ) | escaped-special-chars ; string-escaped-special-chars = character-escaped-special , { character-escaped-special } ; string = character , { character } ; digit = zero | digit-non-zero ; digit-non-zero = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; zero = "0" ; space = " " ; circumflex = "^" ; double-quote = '"' ; square-brackets = "[" | "]" ; parentheses = "(" | ")" ; comma = "," ; semicolon = ";" ; equal = "=" ; character = ? Unicode Characters ? ;
Unicode字符
CFI定义中容许的Unicode字符与[XML 1.0]定义同样。下面为一些排除的代理块(Unicode术语)以及0xFFFE和0xFFFF:
#x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
文档中应该少用“兼容字符集”,如定义在Unicode规范2.3节的那些。下面定义的字符集范围同样不推荐。它们要么是控制字符,要么是永不定义的Unicode字符:
[#x7F-#x84], [#x86-#x9F], [#xFDD0-#xFDEF], [#x1FFFE-#x1FFFF], [#x2FFFE-#x2FFFF], [#x3FFFE-#x3FFFF], [#x4FFFE-#x4FFFF], [#x5FFFE-#x5FFFF], [#x6FFFE-#x6FFFF], [#x7FFFE-#x7FFFF], [#x8FFFE-#x8FFFF], [#x9FFFE-#x9FFFF], [#xAFFFE-#xAFFFF], [#xBFFFE-#xBFFFF], [#xCFFFE-#xCFFFF], [#xDFFFE-#xDFFFF], [#xEFFFE-#xEFFFF], [#xFFFFE-#xFFFFF], [#x10FFFE-#x10FFFF].
CFI由一个以epubcfi字符开始和一个以括号括起来的路径或范围构成。epubcfi指示一个特殊的引用方法。路径构建了一个引用到特定位置的结构化有序步骤。范围是一条表示开始和结束范围位置的两个本地(或相对)路径。
步骤要么是导航步骤,要么是终止步骤。导航步骤能够重复屡次(例如:计数元素,处理子节点,或跟随引用)。终止步骤只能是惟一,若是有,必须是最后一个步骤。
在括号中的字符串能够是可扩展的断言:用于提升路径遍历和文档修订过程当中的鲁棒性。断言保留遍历文档元素的额外信息,它为出版物在作一些修订后恢复想要的位置提供了一种可能。
尽管前面语法描述中value的定义容许任何字符,可是,抑扬符号(^)必须用来转义下列字符,以确保它们的存在不会影响语义转换:
例如指向文本2[1]位置的EPUB CFI须要使用转义符:
epubcfi(/6/7[chap05ref]!/4[body01]/10/2/1:3[2^[1^]])
在路径和范围中,对数字和整数使用时应知足如下规则:
2.3 字符转义
(略)
斜线(/)后跟一个整数的步骤如下面的方式引用到一个或多个子节点:
[译注:]对于3.1.10示例文档而言,epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3[yyy])的完整表示为:epubcfi表示规范,/6表示文档包中的第三个元素(偶数计数),即spine元素,/4[chap01ref]! 其中,/4表示spine的第二个子元素itemref,id为chap01ref表示为[chap01ref],后面的感叹号表示须要间接解析,即访问idref属性:chapter01,该元素在文档包中manifest定义,引用“chapter01.xhtml"文件,后面的步骤为该文件的解析,/4[body01]表示第二个元素,body元素,具备id="body01",ID必须出现;接着,/10[para05]表示body的第五个子元素p, 有id="para05", 接着是/2表示p元素的第一个子元素em;接着,/1:3[yyy]为最后一个元素--终止元素,/1表示第一个非元素的文本,:3表示字符偏移,[yyy]表示便宜位置前的断言,断言第三个字符后(序号基于0)位置上前面为yyy字符。
这个索引的方法确保节点标识对XML解析器处理空白文本,CDATA节和实体引用是不敏感的。(例如能够避免产生如下依赖,一个XML解析器是否折叠只有空格的文本节点,或保持文本,CDATA节或实体引用做为独立的节点,或打断在多个节点中的文本)。
对于标准EPUB CFI ,前导CFI必须以斜线(/)开始,后面跟一个表示在包文档根元素package下的spine子节点的引用位置的偶数。被CFI遍历的包文档必须在出版物的META-INFO/container.xml文件中指定为缺省文档(例如,包文档经过container.xml文件中的第一个rootfile元素定义)。
对于内部EPUB CFI,第一个步骤必须用斜线(/)开始,跟一个引用到以package开始的根元素的引用位置的节点编号。
当EPUB CFI引用到一个包含ID的元素是,相应的路径步骤必须在方括号中包含该ID(例如,在斜线和指示元素的偶数后面)。
标识符规范增长量CFI架构的鲁棒性:阅读系统能够确认CFI指向的位置是否有原来想要的位置,而且,可使用这个标识符计算一些到达指望目标位置的步骤(参见有意目标位置校订)。增长鲁棒性所产生的反作用是对CFI字符串比较(排序)可能须要跳过全部中括号后才能够执行(参见排序规则)。
一个以感叹号(!)开始的步骤指示后面的引用必须被跟踪,并引用到新的目标节点(或引用的一个完整的XML文档的根元素)。
仅下面的引用被接受:
注意:这个规范没有考虑超连接,仅仅考虑了嵌入式引用,所以,跟踪一个HTML5或SVG中的a元素是无效的。
带冒号的终止步骤,跟一个整数表示一个字符偏移。字符偏移能够应用到一个HTML5中的img元素节点,并且该节点必须包含一个alt属性,其中的字符偏移被引用。
对于文本节点,偏移是从零开始的,而且老是指向字符间的位置,因此0意味着第一个字符的前面,一个等于UTF-16总长度的数表示最后一个字符。不能指定大于可用文本的UTF-16最大长度的字符偏移值。
一个字符偏移终止步骤能够呈现为/N的步骤。对于XML内容文档,但参考img的alt文本时,N应该是一个偶数;引用普通文本节点时,N应该是一个奇数。
字符偏移终止步骤后面不能有其余步骤。
以波浪符号(~)开始跟一个数字的终止步骤表示音频或视频的时间偏移,单位为秒。
时间偏移终止步骤后面不能有其余步骤。
以@符号开头更两个冒号分隔数字的终止步骤表示一个图片或视屏中二维(2D)空间位置。这两个数字表示x和y坐标的缩放比例位置,而且,不管视频或图片的显示维度,该值得范围始终是0~100之间(例如:0:0表示左上角,100:100表示右下角)。
空间偏移终止步骤后面不能有其余步骤。
时间和空间位置能够一块儿使用。这种状况下,语义上,时间规范必须在空间规范以前(例如:~23.5@5.75:97.6引用到视频的23.5秒靠左下的边框位置)。
时间偏移终止步骤后面不能有其余步骤。
EPUB CFI能够在设定的位置上指定前面或后面跟随的字符的断言,而且这些断言必须出如今字符偏移终止步骤以后。
例如:下列表达式断言”yyy”在指定位置的以前出现(使用下面的示例内容)
epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3[yyy])
在一个冒号后面的一个额外的子串能够断言指定位置点后面出现。例如:
epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/1:3[xx,y])
经过星号标记引用指向的位置:
x x x y y y 0 1 2 3 4 5 6 7 8 9 | | | * | | | | | | | | | | | |
若是没有指定前面的文本,或者只有后面的文本被指定,一个冒号必须必须在文本断言以前出现,例如:
epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3[,y])
对断言匹配能够包含的做为前导或后随的文本数量没有限制。文本取至文档,忽略元素边界,而且空格老是被压缩(例如,非空序列连续的空格老是被一个空格所代替)。
阅读系统能够经过CFI肯定引用的位置是不是原始想要的位置(因为比匹配的文本),而且可使用前导后后随文本去计算指望达到的位置(参见有意目标位置校订)。添加鲁棒性的反作用是比较(排序)CFI字符串时可能须要跳过全部以中括号包括的字符串(参见排序规则)。
在一些状况下,保留引用指向位置的边界是重要的。例如,在一个动态分页的环境中当解析一个位置时,位置表示指向以前仍是以后的内容是有些不一样的(例如,在分页位置上的引用,决定显示左边仍是右边的页面时就须要考虑边界偏好)。
s参数用于保留引用位置的边界观点,它具备liangge 值:b表示引用位置以前的内容,而a表示以后的内容。这个参数必须在CFI的最后一个步骤中使用,并只能在方括号中使用,即便XML的ID或断言文本为空也可使用。
在下面示例内容中yyy后面的位置能够经过边界偏好表示为属于该引用以前的内容:
epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3[;s=b])
一样,他能够表达在一个文本断言后面:
epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3[yyy;s=b])
表示em元素开始以前的位置能够用以下方式表示:
epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2[;s=b])
若是前面的例子中,把b设置成a,那么所表示的位置是em元素的子内容,而不是em元素后面的内容。
因为边界偏好表达为一个参数,对CFI比较而言,它没有特殊须要处理的。
边界对于空间边界没有定义。
注意:边界偏好仅在一些分隔符位置才有意义(例如:分页符或换行符)
给定一个下列文档包:
<?xml version="1.0"?> <package version="2.0" unique-identifier="bookid" xmlns="http://www.idpf.org/2007/opf" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf"> <metadata> <dc:title>...</dc:title> <dc:identifier id="bookid">...</dc:identifier> <dc:creator>...</dc:creator> <dc:language>en</dc:language> </metadata> <manifest> <item id="toc" properties="nav" href="toc.xhtml" media-type="application/xhtml+xml"/> <item id="titlepage" href="titlepage.xhtml" media-type="application/xhtml+xml"/> <item id="chapter01" href="chapter01.xhtml" media-type="application/xhtml+xml"/> <item id="chapter02" href="chapter02.xhtml" media-type="application/xhtml+xml"/> <item id="chapter03" href="chapter03.xhtml" media-type="application/xhtml+xml"/> <item id="chapter04" href="chapter04.xhtml" media-type="application/xhtml+xml"/> </manifest> <spine> <itemref id="titleref" idref="titlepage"/> <itemref id="chap01ref" idref="chapter01"/> <itemref id="chap02ref" idref="chapter02"/> <itemref id="chap03ref" idref="chapter03"/> <itemref id="chap04ref" idref="chapter04"/> </spine> </package>
和XHTML内容文档chapter01.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>...</title> </head> <body id="body01"> <p>...</p> <p>...</p> <p>...</p> <p>...</p> <p id="para05">xxx<em>yyy</em>0123456789</p> <p>...</p> <p>...</p> <img id="svgimg" src="foo.svg" alt="..."/> <p>...</p> <p>...</p> </body> </html>
如EPUB CFI:
epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/3:10)
引用到ID为para05的段落中数字9的后面位置。
当须要为文本位置生成一个CFI是,除非文本由img元素的alt属性定义,文本位置应该老是开始于文本节点或文本节点集合(即便为空),并计数到相应的位置,让后一直跟踪它的祖先一直到文档包的根节点。
下面例子显示EPUB CFI如何构造一些内容位置的引用:
引用到img元素:
epubcfi(/6/4[chap01ref]!/4[body01]/16[svgimg])
引用到xxx位置以前:
epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/1:0)
引用到yyy位置以前:
epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:0)
引用到yyy位置以后:
epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3)
为计算或排序引用到同一出版物的多个EPUB CFI的相对位置时,下列规则必须应用:
内部出版物能够在容器内引用。这类引用可以指定一个引用到文档包的CFI来归档,这个CFI必须从跟节点开始解析。
例如,使用在前面示例的文档包,在第二章(chapter02.xhtml)中引用到上例中最后一个示例的位置能够表示以下:
<a href="../pub.opf#epubcfi(/6/4[chap01ref]!/4[body01]/10[para05]/2/1:3[;s=b])">location</a>
EPUB CFI容许扩展开始到结束位置的简单范围表达式。一个范围表达式必须表达为一个三元组:父路径,开始子路径,结束子路径,或如下形式:
epubcfi(P,S,E)
父路径必须中止在开始和结束位置范围路径的共同部分,而且,开始和结束子路径必须以非增长的顺序解析到文档位置。
为肯定范围开始和结束的位置,开始和结束子路径必须能够链接到父路径以建立开始位置路径(PS)和结束路径(PE)。
使用前面的示例文档,下面的范围描述了从yyy中的第二个yzifu 到数字3(包含3):
epubcfi(/6/4[chap01ref]!/4[body01]/10[para05],/2/1:1,/3:4)
范围必须依照PS而后再PE来比较。
使用一个指向元素的路径来代替元素的开始和结束位置是无效的。单个路径表示法老是标注一个位置,而且,范围由上面描述的表示法表示。这里没有一个能够产生指向元素结尾的特殊的步骤,若是有,那么对CFI的排序而言,若是不查询文档内容将是不可能完成的。
假如范围使用在上下文期待的单个位置,开始位置必须使用。
边界偏好参数不能在范围中使用,范围的开始暗示开始位置以后的内容,结束暗示着结束位置以前的内容。
正如一个EPUB出版物可能随着时间的推移,须要更新,校订或修改,可以从前一个版本的标注为修改后的文档推断一个EPUB CFI是有用的。本规范提供了两种机制去检测或适应内容改变对CFI的影响:XML中的ID和文本位置断言。
当一个阅读系统在处理CFI时,它应该检查任何遇到断言的正确性。例如,给定路径/6/4[chap01ref]!...,阅读系统应该在处理原素4时验证元素的ID是否匹配chap01ref(对于本例,在spine中的itemref属性)。若是不匹配,阅读器应该定位在文档中的chap01ref,并校订CFI(例如,若是一个新的itemref插入在chap01ref的itemref前面,这样,实际指望的元素序号如今变成了6,而且校订的CFI应该为/6/6[chap01ref]!...)。一样,文本位置断言应该用于检查引用的目标位置,并使用它为期待的文本位置推断校订后的CFI。
若是在处理过程当中,有一个断言失败,一个校订的CFI也不能推断(ID在文档中没有找到,或匹配的文本没有找到),CFI必须认为这是一个无效引用。在阅读器不能检查其正确性的状况下(例如,在CFI处理阶段驻留文档的XML ID不可用时),它必须忽略CFI断言。
校订CFI的概念会致使两个不一样的CFI指向同一位置的状况(例如,老的CFI,准备校订的和已经校订的)。校订后的CFI应该在可能的状况下使用。阅读器和任何围绕内容管理的系统应该试图在可能的状况下用校订好的版本替换陈旧的CFI。
注意:本规范鼓励自定义功能开发辅助CFI校订,目前在校订上的功能是不够的。更多开发这些功能的信息参考扩展EPUB CFI。
提供扩展(CSV参数列表,参数名前缀,而且用分号分开)容许阅读器应用新的或启发性的实验去辅助迁移EPUB CFI片断以更新文档。
强烈建议任何厂商规范名称以vnd开始,后面跟厂商名称。
全部实现必须忽略全部不能理解或不能转换的参数。
正式参考
[EPUBCFI] EPUB Canonical Fragment Identifier (epubcfi) Specification .
[HTML5] HTML5: A vocabulary and associated APIs for HTML and XHTML .
[RFC2119] Key words for use in RFCs to Indicate Requirement Levels (RFC 2119) . March 1997.
[RFC2279] UTF-8, a transformation format of ISO 10646 (RFC 2279) . F. Yergeau, et al. January 1998.
[RFC2396] Uniform Resource Identifiers (URI): Generic Syntax (RFC 2396) . T. Berners-Lee, et al. August 1998.
[RFC2732] Format for Literal IPv6 Addresses in URL's (RFC 2732) . R. Hinden, et al. December 1999.
[RFC3986] Uniform Resource Identifier (URI): Generic Syntax (RFC 3986) . Berners-Lee, et al. January 2005.
[RFC3987] Internationalized Resource Identifiers (IRIs) (RFC 3987) . M Duerst, et al. January 2005.
[SVG] Scalable Vector Graphics (SVG) 1.1 (Second Edition) . Erik Dahlström, et al. 09 June 2011.
[XML] Extensible Markup Language (XML) 1.0 (Fifth Edition) . T. Bray, et al. 26 November 2008.
非正式参考
[XPTRSH] XPointer Shorthand Notation .