HTML 片段的解析和创建






3.08/5 (9投票s)
2003年1月9日
3分钟阅读

85363

964
将 HTML 部分解析为对象树并返回的类
引言
当查看 Page
对象的 Controls
集合时,您会很快意识到所有有趣的东西都包含在 LiteralControl
中。 因此,没有简单的方法可以舒适地插入或更改此文本。 因此,我编写了一些类,可以将字符串分解为对象。 这些对象可以安全地更改,然后为 LiteralControl
生成一个新的字符串。
我在编写页面模板类时遇到了这个问题。 您可以将文字代码从 .aspx 文件中取出,但随后设计器似乎无法很好地工作。 所以我喜欢使用设计器并更改页面模板中的页眉文字。
背景
解析 HTML 并不是一件有趣的事情,所以我做了一些限制。
- 解析器实际上并不理解 HTML,而只理解文本、标签和属性。 他不关心他们的名称和值是什么。
- 格式错误的输入将导致输出不佳。(即,
<meta>
通常不会关闭,因此放置后续标签的唯一方法是作为子标签。 因此,源文本必须更改为类似<meta ... />
。) - 由于您可以将纯文本插入到生成的对象树中,因此您很容易破坏输出。(即,插入像
"<junk"
这样的文本将被呈现为"<junk"
而不是<junk"
。请记住,大脑在屏幕前面 :-)
使用代码
主要的类是 Fragments
。 Fragments
的构造函数接受一个字符串,该字符串被解析为对象。 Fragments
是一个(猜猜是什么?)Fragement
的集合。 实际上 Fragment
是 FragmentText
(表示简单的纯文本)、FragmentTag
(表示一个标签 <tagname attr="value" ... >
)、FragmentComment
(表示注释 <!-- ... -->
和 Fragmen
t
Doctype
(即 <!DOCTYPE HTML ... >
)。
对象可以像在任何集合中一样被更改、添加或删除。 类型为 FragmentTag
的对象具有一个属性 Nodes
,它表示子标签。 由于我们解析的是一个片段,因此可能存在不匹配的标签(即,只有开始或只有结束标签。因此,FragmentTag
具有一个属性 Type
,它声明是否存在开始和/或结束标签。 值 OpenCloseShort
代表 <br/>
类型的标签。 显然,这些标签不能有 Nodes
。
最后,使用 ToString()
方法将 Fragment
转换为纯 HTML 字符串。
Fragments fragments = new Fragments( someString );
for each ( Fragment fragment in fragments )
{
if ( fragment is FragmentTag )
{
FragmentTag tag = (FragmentTag)fragment;
tag.Nodes.Add( new FragmentText( "plain text" ) );
}
if ( fragment is FragmentText )
{
...
}
}
string s = fragments.ToString();
您也可以从一个空的 Fragments
对象开始,将所有内容插入其中并生成输出。
有一个带有源代码的小示例程序,我用它来进行测试。 它演示了大多数用法。
关注点
我使用 Regex
类将输入分割成碎片。 该模式相当难以阅读,但基本结构是 pattern1|pattern2|pattern3|...
。 我花了一些时间才明白,下一个匹配项将包含这些模式中的一个。 我在那里给每个模式一个独占的名称,并为参数或名称创建了一些子组。 还要注意的是,下一个匹配项不会完全在上次匹配项之后继续。 它只会继续在那里搜索。 因此,我们必须自己跟踪是否已解析所有输入。
历史
- Version 1.0 - 首次发布
- Version 1.1 - 错误修复(异常内部的异常,嵌套引号的解析)