本节书摘来自异步社区《重构HTML:改善Web应用的设计(修订版)》一书中的第2章,第2.6节,作者: 【美】Elliotte Rusty Harold 更多章节内容可以访问云栖社区“异步社区”公众号查看。
2.6 TagSoup
John Cowan的TagSoup是一个用Java编写的开源HTML解析器,它实现了XML或SAX的一些简单API。Cowan说它是一个“用Java编写的兼容SAX的解析器,不是解析良构或有效的XML,而是解析世界上大量存在的劣质、污秽和粗野的HTML,虽然很多时候远远处理不了。TagSoup是为那些使用形似合理的软件处理这些问题的人们而设计的。通过提供SAX界面可以把标准的XML工具应用到甚至最坏的HTML上。”
TagSoup并没有计划做成一个供最终用户使用的工具,但还是提供了一些基本的命名行界面。还可以将它跟很多能从SAX中接受输入的XML工具直接挂钩,然后输入HTML,就能得到良构的XHTML,例如:
java -jar tagsoup.jar index.html
<?xml version="1.0" standalone="yes"?>
<html lang="en-US" xmlns="http://www.w3.org/1999/
xhtml"><head><title>Java Virtual Machines</title><meta
name="description" content="A Growing
list of Java virtual machines and their capabilities">
</meta></head><body bgcolor="#ffffff" text="#000000">
<h1 align="center">Java Virtual Machines</h1>
...
你可以稍微改善输出,只需加上--omit-xml-declaration和-nodefaults命令行选项:
$ java -jar tagsoup.jar --omit-xml-declaration
-nodefaults index.html
<html lang="en-US" xmlns="http://www.w3.org/1999/
xhtml"><head><title>Java Virtual Machines</title><meta
name="description" content="A Growing
list of Java virtual machines and their capabilities"></meta>
</head><body bgcolor="#ffffff" text="#000000">
<h1 align="center">Java Virtual Machines</h1>
...
这会删除一些可能会让某些浏览器困惑的代码。
还可以用--encoding选项指定输入文档的字符编码。比如,如果你知道文档是用Latin-1、ISO8859-1写的,则可以如此运行:
$ java -jar tagsoup.jar --encoding=ISO-8859-1 index.htm
l```
TagSoup的输出永远是UTF-8。
最后,你可以使用--files选项来复制输入文件为以.xhtml为后缀的新文件。否则,TagSoup直接打印到标准输出中,但可以将输出重新放置到任何合适的地方。TagSoup不能像Tidy那样直接改动文件。
然而,TagSoup主要是作为一个库来用的。跟Tidy比起来,来自命令行模式的输出需要解决一些问题,包括:
- 没有把表现性标记转为CSS;
- 不包含DOCTYPE声明,一些浏览器需要它来认出XHTML;
- 包含了XML声明,这会让一些旧的浏览器困惑;
- 对于空元素(如br和hr),它同时使用起始标签和结束标签⑤,同样会让一些旧的浏览器困惑。
TagSoup不能保证XHTML绝对有效(尽管能保证良构),有些东西它也是处理不了的。最重要的是,XHTML要求所有的img元素都有一个alt属性。如果alt的值是空的,那么这个图片完全是表现性的,屏幕阅读器(screen reader)应当要忽略它。反之,alt有内容的话,屏幕阅读器就会以内容替代图片的显示。TagSoup没有办法知道省略了alt的图片是否为表现性的,所以它不会插入这个属性。类似地,它也不会插入表格的摘要。你需要手工完成这些需求,在使用TagSoup后马上进行验证,以尽快确定问题所在。
虽然有这些限制,但TagSoup确实可以为你做很多低投入高产出的工作。
TagSoup与Tidy
对最终用户来说,TagSoup和Tidy最大的不同之处在于理念上的差异。Tidy对问题有时会放弃以及征求你的帮助,有些不知道该怎么去修复的问题,它也不会尝试去修复。TagSoup则永不放弃,它最终一定会输出良构的XHTML,虽然不总能产生有效的XHTML,但还是能帮你不少忙。基于同样的理由,TagSoup不会提示它处理不了而让你能够手工去修复的问题。它假设你不在乎它的做法。如果你在乎的话,你或许更愿意使用Tidy,Tidy更细心,在不是非常确定文档的意思时,它不会给出方案,而TagSoup一定要给出结果才罢休。