65.9K
CodeProject 正在变化。 阅读更多。
Home

Xport: XHTML 解析和报告工具包

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.73/5 (10投票s)

2008年3月21日

GPL3

13分钟阅读

viewsIcon

61603

downloadIcon

715

用于生成和解析 xhtml 文档的开源 C++ 类模板库。

引言

Xport,XHTML parsing & objective reporting toolkit(XHTML 解析和客观报告工具包),是一个 C++ 模板类库,可以包含在任何 C++ 项目中,用于创建和生成 xhtml 文档。尽管 Xport 的开发初衷是为了创建用于报告目的的 xhtml 文档,但 Xport 也可以用于创建许多其他用途的 xhtml 文档。

Xport 还提供了 xhtml 和样式表解析功能。Xport 可以解析几乎任何 xhtml 文档,以及格式不太差的 HTML 文档。

Xport 提供了生成和解析各种文档类型的能力。Xport 提供了三种文档类型类:xhtml strict 1.0、xhtml transitional 1.0 和 xhtml frameset 1.0。Xport 的灵活设计还允许轻松包含其他文档类型。无论您使用哪种文档类型,Xport 都会强制执行该特定文档类型的规则。

Xport 还提供了使用标准字符类型或宽字符类型来支持 Unicode 的能力。

Xport 中提供了多种迭代器,可在处理文档、元素和样式表时提供类似 STL 的功能。这些迭代器与 STL 容器和算法兼容。还提供了一个后代迭代器,用于遍历文档树或文档中的子树。使用 STL 的算法,可以快速轻松地找到文档树中任何可识别的元素。

Xport 包含一个设计良好的类层次结构和一个丰富且文档齐全的接口。关键类的命名恰当,以传达其用途。类型名称,如 documentelementmarkupcommentstylesheetstylesheet_rule,使得使用这些类直观易懂。尽管 Xport 完全由类模板组成,但使用 Xport 时无需使用模板语法,因为所有各种类模板和文档类型都提供了类型别名。Xport 中关键类的许多操作都反映了 STL 容器中的操作,提供了直观且友好的接口。

从上面的链接中可用的文档详细介绍了每个类的每个操作,并为 Xport 所有类的每个公共操作提供了示例。

使用代码

尽管 Xport 完全由类模板组成,但您无需了解模板知识即可使用 Xport 及其所有功能。Xport 中提供了类型别名,允许在不直接处理模板类的情况下使用它。例如,以下代码片段创建并保存了一个基本的 xhtml strict 文档。

// bring namespace into current scope 
using namespace Xport; 

// create an xhtml document with the root elements 
// (<html>, <head>, and <body>)
document doc(root_doc); 

// insert a paragraph element into the document's 
// body element, returning an iterator
markup::iterator it = doc.body()->insert(element(p)); 
it->insert("This is the first paragraph of the document"); 

// insert a paragraph into the document using the 
// insertion operator
*doc.body() << (element(p) 
          << "This is the second paragraph of the document"); 

// write the document
doc.write("c:/myDoc.htm"); 

使用 Xport 的样式表类,创建样式表也同样容易。下面的示例演示了如何创建带有链接样式表的简单 xhtml 文档。

// the following include gives access to all Xport's interface
#include "xhtml_doc.h"

using namespace Xport;
// create a root document called 'doc'
document doc(root_doc); 

// insert a title in the head element 
*doc.title() << "Sample xhtml document";

// insert a heading into the documents body
*doc.body() << (element(h1) 
            << "This is a sample xhtml document!");

// insert paragraph
markup::iterator it = doc.body()->insert(element(p));
*it << "This document was created by Xport, "
    << "to demonstrate it's xhtml generation features. "
  << "pcdata can be inserted into elements all at once, "
  << "or seperately. The push_back() operation behaves "
  << "similar to the insert() operation when insert() "
  << "is supplied a single argument.  When supplied a "
  << "single argument (the pcdata to insert), "
  << "the insert() operation inserts the object/pcdata "
  << "at the end of the called element. "
  << "But when supplied with an additional argument, "
  << "a child iterator, the child iterator "
  << "specifies where the object/pcdata will be inserted.";

// insert user list
it = doc.body()->push_back(element(ul)); 
*it << (element(li, "li1") << "List item 1");
*it << (element(li, "", "red") << "List item 2");
*it << (element(li, "", "red") << "List item 3");

// create stylesheet object
stylesheet ss;

// add rule for heading
stylesheet::iterator sit = ss.insert(stylesheet_rule("h1"));
*sit << declaration(css::color, "red")
    << declaration(text_align, "center");

// add rule for paragraph
sit = ss.insert(stylesheet_rule("p"));
*sit << declaration(margin_left, "30px")
     << declaration(padding, "10px")
     << declaration(css::width, "400px")
     << declaration(css::border, "thin groove blue");

// add rule for user list
sit = ss.insert(stylesheet_rule("ul"));
*sit << declaration(padding_left, "20px");

// add rule for element id li1
sit = ss.insert(stylesheet_rule("#li1"));
*sit << declaration(css::color, "green");

// add rule for class selector red
sit = ss.insert(stylesheet_rule("li.red"));
*sit << declaration(css::color, "red");

// add stylesheet link to document header
it = doc.head()->insert(element(Xport::link));
it->attribute(rel, "stylesheet");
it->attribute(type, "text/css");
it->attribute(href, "test_doc.css");

// write the document object to a file
formatter fmtr("c:/test_doc.htm");
fmtr.option(max_line_length, 80);
doc.write(fmtr);

// write the stylesheet object to a file
ss.write("c:/test_doc.css");

以下类构成了 Xport 的接口

xhtml 类

xhtml_class_diagram.png

Xport 的 xhtml 类支持创建和解析 xhtml 文档的功能。如上所述,Xport 完全由类模板组成,但为方便用户使用,为所有接口类声明了类型别名。xhtml 模板类被参数化为两种类型:文档类型字符类型。下表列出了 Xport 的所有 xhtml 接口类模板以及这些类可用的类型别名。

类模板 类型别名
xhtml
strict
wchar xhtml
strict
xhtml
transitional
wchar
xhtml transitional
xhtml
frameset
wchar xhtml
frameset
xhtml_doc 文档 wdocument tdocument wtdocument fdocument wfdocument
xhtml_markup markup wmarkup tmarkup wtmarkup fmarkup wfmarkup
xhtml_element element welement telement wtelement felement wfelement
xhtml_pcdata pcdata wpcdata tpcdata wtpcdata fpcdata wfpcdata
xhtml_comment comment wcomment tcomment wtcomment fcomment wfcomment
xhtml_processing_instruction procinstr wprocinstr tprocinstr wtprocinstr fprocinstr wfprocinstr
xhtml_formatter formatter wformatter tformatter wtformatter fformatter wfformatter
xhtml_parser parser wparser tparser wtparser fparser wfparser
表 1:Xport 的 xhtml 类模板和类型别名

Xport 的默认文档类型是 xhtml strict,在上面的表中以蓝色显示。大多数示例报告将反映此文档类型。因此,库的用户通常只会使用上面蓝色显示的类型别名来创建文档。

下面简要描述了 Xport 的 xhtml 类型。将使用默认类型别名来描述可用的不同 xhtml 类型。

文档

在 Xport 中,文档 类型封装了一个 xhtml 文档。document 对象是您将使用的最重要的对象之一。document 对象以树结构或文档树 的形式组织其内容。标准 xhtml 文档通常包含 htmlheadtitlebody 元素。在 Xport 中,这些元素被称为根元素,包含这些根元素的 document 被认为是根文档。创建 document 对象时,您可以选择将其创建为根文档,并包含这些根元素。这些根元素以及其中包含的所有其他元素构成了文档树。一旦将内容添加到 document 中,就可以将 document 写入文件或流。document 对象还可以解析 xhtml 文件以及 html 文件。解析 html 文件的结果将因 html 文件的形式而异。

markup

markupelementcommentprocinstr 的基类型。markup 主要用于 Xport 的标记迭代器,下面将进一步讨论它们。所有标记迭代器都返回 markup 对象的引用和指针,这些对象实际上是从 markup 派生的对象。因此,markup 的接口确实非常重要,因为只有通过 markup 的接口,我们在使用标记迭代器时才能访问从 markup 派生的那些对象。

element

Xport 的 element 类型封装了一个 xhtml 元素。在创建文档内容时,element 对象比任何其他对象类型使用得都更频繁。element 对象是唯一可以包含其他 markup 对象的 markup 对象,这使得 element 对象承担了构成文档树的责任。有多种方法可以将其他 markup 对象添加或插入到 element 对象中,这些方法都已在文档和示例中进行了详细介绍。Xport 只允许将元素插入到不违反所用文档类型规格的元素中。例如,Xport 不允许将 p 元素插入到另一个 p 元素中,因为这对于所有文档类型来说都违反 xhtml。每种文档类型都有特定的规则,或文档类型定义,Xport 会强制执行这些规则。

element 在其构造函数中接受三个参数。第一个参数是必需的,用于指定要创建的元素的标签名。在 Xport 中,为了方便起见,标签名被枚举了。第二个可选参数用于指定元素的id 属性,第三个可选参数用于指定元素的class 属性。

element 还可以被赋予属性,这些属性也为了方便起见进行了枚举。文档类型定义指定了哪些属性可以分配给哪些元素,Xport 也会强制执行这些规则。Xport 还提供了一种简单的方法来为特定元素分配样式,通过样式属性,但由于 Xport 支持样式表,因此鼓励使用样式表而不是样式属性。

pcdata

Xport 的 pcdata 类型封装了 xhtml 文档中的 PCDATA(可解析字符数据)。pcdata 对象在 Xport 中主要被隐式使用。每当将文本插入到元素中时,Xport 就会将文本放入一个 pcdata 对象中。当一个 element 包含 PCDATA 时,该 element 将包含一个或多个 pcdata 对象,这些对象包含 PCDATA。构成元素内 PCDATA 的 pcdata 对象的数量取决于 PCDATA 插入到 element 中的方式。

无论元素是表示为 element 对象还是 pcdata 对象的一部分,当 Xport 解析 (x)html 文档时,parser 始终会将元素(包括内联元素)解析为 element 对象,而不是将它们包含在 pcdata 对象中。这意味着,例如,如果一个段落元素包含包含内联元素和 PCDATA 的内容,该段落元素将被解析为多个独立的 pcdata 对象和 element 对象。

comment

Xport 的 comment 是一个非常简单的类型,封装了一个 xhtml 注释。注释在 xhtml 中不是必需的,但它们对于记录 xhtml 源非常有用。与 element 一样,comment 也派生自 markup,并且也被视为 markup 对象。

procinstr

Xport 的 procinstr 封装了一个 xhtml 处理指令。Xhtml 中有许多形式的处理指令,但所有处理指令都用 **<?** 和 **?>** 分隔。最常见的处理指令类型之一是 PHP 处理指令。procinstr 也派生自 markup,并且也被视为 markup 对象。

formatter

Xport 的 formatter 用于格式化文档的输出,无论是输出到文件还是流。formatter 对象提供了对 xhtml 输出的详细控制。使用 formatter,您可以指定文档中任何元素的布局样式。您还可以指定最大行长度以及文档中实体的呈现方式。事实上,借助 Xport 的 parser 和 Xport 的 formatter,您可以使用该工具包来简单地按照您的喜好重新格式化现有的 xhtml 文档。

parser

Xport 的 parser 允许解析 xhtml 和 html 文档。如果 xhtml 格式正确,parser 对象将毫无问题地解析该文档。如果文档格式不正确,parser 对象将尽力解析该文档并处理其错误。parser 对象会将文件或流解析为 Xport document 对象。无论要解析的文档有多差,生成的 document 对象将始终是格式良好的,因为 Xport 不允许无效的 xhtml。parser 对象还允许用户指定文档解析方式的选项,使用户能够控制换行符保留、实体转换和字节顺序标记保留等内容。parser 对象可以根据需要生成其进度日志。

样式表类

stylesheet_class_diagram.png

Xport 的样式表功能通过另一组模板类实现,这些类仅由字符类型进行参数化。与 xhtml 模板类一样,为样式表模板类声明了类型别名,以使其更容易使用。下表说明了样式表模板类及其类型别名。

类模板 类型别名
窄字符 宽字符
xhtml_stylesheet stylesheet wstylesheet
xhtml_stylesheet_rule stylesheet_rule wstylesheet_rule
xhtml_stylesheet_import stylesheet_import wstylesheet_import
xhtml_stylesheet_comment stylesheet_comment wstylesheet_comment
stylesheet_declaration declaration wdeclaration
表 2:Xport 的样式表类模板和类型别名

Xport 的样式表类型别名的默认字符类型是标准窄字符类型。使用标准窄字符,库用户将只使用表中左侧以蓝色显示的类型别名。Xport 的 stylesheet 对象封装了一个级联样式表。stylesheet 对象可以轻松地写入文件,或嵌入到文档中。Xport 的 stylesheet 对象还可以解析现有样式表,从文件或流中解析。

下面简要描述了 Xport 的样式表类型。将使用默认类型别名来描述可用的不同样式表类型。

stylesheet

Xport 的 stylesheet 封装了一个级联样式表。stylesheet 的接口很小,但非常重要。它的三个操作 add_item()write()parse() 赋予了 stylesheet 主要功能。有三种类型的对象可以添加到 stylesheet 对象中:stylesheet_rulestylesheet_commentstylesheet_import。这使得 stylesheet 对象比 document 对象更简单。将样式表添加到文档的大部分工作涉及下面详细介绍的 stylesheet_rule

stylesheet_rule

Xport 的 stylesheet_rule 封装了一个 CSS 规则。在 Xport 中创建样式表时,stylesheet_rule 对象比任何其他样式表类型使用得都多。由于样式表规则总是包含一个选择器,该选择器指定了规则适用的文档部分,因此 stylesheet_rule 在其构造函数中接受一个必需的字符串参数,该参数指定了规则的选择器。创建 stylesheet_rule 对象后,通过 add_declaration() 操作向其添加声明。这是 stylesheet_rule 中的主要操作,并且有两种形式。第一种形式接受一个 declaration 对象,该对象将在下面介绍。第二种形式的操作接受两个参数。第一个参数指定 css property(属性),第二个参数指定该属性的value(值)。css 属性名称为了方便起见被枚举了。属性值被指定为字符串参数。

stylesheet_import

Xport 的 stylesheet_import 有一个基本目的,即允许将另一个样式表导入到当前样式表中。

stylesheet_comment

Xport 的 stylesheet_comment 封装了一个样式表注释。此类型允许用户向样式表中添加注释。

declaration

Xport 的 declaration 封装了一个 CSS 声明。一旦创建了 declaration 对象,就可以将其添加到 stylesheet_rule 中。declaration 在其构造函数中期望两个必需的参数。第一个参数指定 css property(属性),第二个参数指定该属性的value(值)。

迭代器类

Xport 的迭代器功能可用于 xhtml 标记和样式表。标记有两种类型的迭代器:子标记迭代器和后标记迭代器。顾名思义,迭代器遍历元素或文档的直接子级,而迭代器遍历所有后代。

下面简要描述了 Xport 的迭代器类型。

markup::iterator 和 markup::const_iterator

Xport 的子标记迭代器 iteratorconst_iterator 对于创建和解析 xhtml 文档都非常有用。这些迭代器不仅允许遍历子标记对象,还可以用于插入、添加和删除子标记对象。特别是 iterator 非常有用,它从元素的 insert() 操作中返回。返回的 iterator 进而可以用于在 iterator 指向的元素中插入其他标记。鼓励用户在文档中生成内容时大量使用 iterator

markup::descendant_iterator 和 markup::const_descendant_iterator

当需要遍历文档或文档中特定元素的后代时,使用 Xport 的后标记迭代器 descendant_iteratorconst_descendant_iterator。这些迭代器以预序方式遍历。文档对象的后代迭代器可以遍历整个文档中的每个标记对象,这可能非常方便。与 iterators 一样,后代迭代器也可以用于在文档中插入、添加和删除标记。

stylesheet::iterator 和 stylesheet::const_iterator

Xport 的样式表迭代器 iteratorconst_iterator 对于创建和解析样式表都非常有用。这些迭代器不仅允许遍历样式表项,还可以用于插入、添加和删除样式表项,包括样式表规则、导入规则和注释。特别是 iterator 非常有用,它从样式表 insert() 操作中返回。插入样式表规则时,返回的 iterator 进而可以用于在 iterator 指向的 stylesheet_rule 中插入声明。鼓励用户在样式表中生成样式表项时大量使用 iterator

stylesheet_item::iterator 和 stylesheet_item::const_iterator

Xport 的样式表规则迭代器 iteratorconst_iterator 对于创建和解析样式表规则都非常有用。虽然这些迭代器遍历嵌入在 stylesheet_rule 对象中的声明,但此迭代器在 stylesheet_rule 的基类 stylesheet_item 中声明和定义。

历史

版本 1.6.1

引入到 CodeProject

版本 1.6.5

修复了由与 windows 定义的“small”名称冲突引起的编译器错误。
为 stylesheet_iterator 和 stylesheet_rule_iterator 添加了 operator < 操作。
杂项小错误修复。

版本 1.6.7

修复了 document::insert(stylesheet) 中的错误;
修复了 stylesheet_rule_iterator 中的 const 问题。
删除了未使用的 clear_all 枚举。
VC6 兼容性更改。

有关 Xport 的更多信息以及完整的版本历史记录,请访问 Xport 的主页

© . All rights reserved.