首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

5.4 在HTML文档中查找元素

在HTML文档中与在XML文档中查找元素通常情况下还是有很大不同的。现代HTML事实上是XML的一个子集,这么说来似乎有点自相矛盾。但HTML文档包含了许多本质的不同,而这正是你可以充分利用的地方。

对JavaScript/HTML开发者来说,最重要的两个优势是利用类和CSS选择器(selector)。将这熟记于心,你就可创建一系列强大的函数,使DOM的操作更简单、更易理解。

5.4.1 通过类的值查找元素

通过类名字定位元素是一种很普遍的技术,2003年由Simon Willison(http://simon.incutio. com)普及,而原创的则是Andrew Hayward(http://www.mooncalf.me.uk)。该技术直截了当:遍历所有的元素(或者某元素的所有后代元素)直至找到指定类的元素。一种可能的实现方法如代码清单5-14所示。

代码清单5-14 找出全部有指定类值的元素的函数

function hasClass(name,type) {

  var r = [];

  // 定位到类值上(允许多类值)

  var re = new RegExp("(^|\\s)" + name + "(\\s|$)");

  // 限制类型的查找,或者遍历所有元素

  var e = document.getElementsByTagName(type || "*");

  for ( var j = 0; j < e.length; j++ )

    // 如果元素拥有指定类,把它添加到函数的返回值中

    if ( re.test(e[j]) ) r.push( e[j] );

  // 返回符合的元素列表

  return r;

}

现在你就可使用这个函数来在任意的或者指定类型(比如<li>或<p>)的元素中迅速查找有指定类值的元素。指定标签名会比遍历所有元素(*)的查找更快,因为需检索的目标更少。比如,在我们的HTML文档中,如果需要找出类值有test的所有元素你可以这么做:

hasClass("test")

如果只需找类值有test的<li>元素,则可以这么做:

hasClass("test","li")

当然,如果只需找出类值有test的<li>元素的第一个,则可以这么做:

hasClass("test","li")[0]

这个函数本身就已非常强大,一旦结合getElementById和getElementsByTagName,你就可以创建更强大的工具集合解决大部分棘手的DOM问题了。

5.4.2 使用CSS选择器查找元素

作为一个Web开发者,你应该已经知道选择HTML元素的一种方案:CSS选择器。CSS选择器是用于赋予元素样式的表达式。随着CSS标准(1、2和3)的每次修订,选择器规范增加了越来越多的重要特点,由此开发者更容易精确定位到所需的元素。不幸的是,浏览器对CSS 2和CSS 3的实现慢得不可思议,所以你或许并不知道CSS中某些新奇酷的特点。如果你对这些感兴趣,建议你浏览W3C的这些主题页面:

l    CSS 1选择器:http://www.w3.org/TR/REC-CSS1#basic-concepts。

l    CSS 2选择器:http://www.w3.org/TR/REC-CSS2/selector.html。

l    CSS 3选择器:http://www.w3.org/TR/2005/WD-css3-selectors-20051215/。

每种选择器规范可用的特点基本上都差不多,每一个后续的版本也都包含前一版的所有特点,同时,每次新版都会增加一系列的新特点。举个例子,CSS 2包含了特性(attribute)选择器和子选择器,而CSS 3则提供了额外的语言支持、性质类型选择以及逻辑非等。比如,以下所有这些都是正确的CSS选择器。

l    #main<div>p:该表达式查找一个id为main的元素下所有的<div>元素,然后是这些元素下所有的<p>元素。它们都是CSS 1下的选择器。

l    div.items>p:该表达式查找所有的类值为items的<div>元素,然后定位到所有的子<p>元素。这是正确的CSS 2选择器。

l    div:not(.items):这则定位到所有没有值为items的类的所有<div>元素。这是正确的CSS 3选择器。

现在,你可能会觉得疑惑,实践中如果并不能使用它们来定位元素(而只能赋予样式)的话,为何会在此讨论CSS选择器。实际上很多前卫的开发者已经涉足开发能兼容CSS1甚至完全支持CSS 3的选择器的实现。使用这些库能让你顺利、方便地选择任意元素并对它们进行操作。

1.cssQuery

第一个完全支持CSS 1-3可用的公开库叫cssQuery,由Dean Edwards(http://dean.edwards.name)创立。其背后的动机很简单:你提供CSS选择器,cssQuery帮你找出所有匹配的元素。此外,cssQuery可以分解成多个子库,有一个是每个CSS选择器“管理员”,它甚至能执行CSS 3的语法,如果有必要的话。这个独特的库非常复杂但能运行在所有现代浏览器上(Dean是一位跨浏览器支持的忠实拥趸)。要应用整个库,你需要提供选择器,也可选择加入上下文元素以便加快搜索。以下是例子:

// 查找所有<div>元素的子<p>元素

cssQuery("div > p");

// 查找所有的<div>, <p>和<form>元素

cssQuery("div,p,form");

// 查找所有<p>元素和<div>元素,然后查找在这些元素内的a元素

var p = cssQuery("p,div");

cssQuery("a",p);

执行cssQuery函数会返回匹配的元素列表。由此你就可以像使用getElementsByTagName一样对元素进行操作。比如,为所有指向Google的链接增加边框,可按如下方法做:

// 为所有指向Google的链接增加边框

var g = cssQuery("a[href^='google.com']");

for ( var i = 0; i < g.length; i++ ) {

  g[i].style.border = "1px dashed red";

}

关于cssQuery的更多信息可以在Dean Edwards的网站上获取,那里同时也提供完整的源码下载:http://dean.edwards.name/my/cssQuery/.

提示 Dean Edwards是一位JavaScript魔术师,他的代码令人惊讶。强烈建议你稍加浏览他的cssQuery库,看看他的JavaScript扩展性写得多么好。

2.jQuery

尽管jQuery是JavaScript库世界的新成员,但它提供了一些新颖而引人注目的JavaScript编程方式。我最初只想把jQuery写成一个“简便”的CSS选择器库,类似于cssQuery,直到Dean Edwards发布了卓越的cssQuery库,迫使我开辟了另一个不同的方向。这个库提供了完整的CSS 1-3的支持,同时也有基本的XPath支持。在此之上,它还提供了进一步定位和操作DOM的能力。跟cssQuery一样,jQuery完全支持现代浏览器。以下是使用混合CSS和XPath的jQuery自定义方式来选择元素的例子:

// 查找所有类值为'links', 同时内有p元素的<div>元素

$("div.links[p]")

// 查找所有<p>, <div>元素的所有子孙元素

$("p,div").find("*")

// 查找指向Google的所有偶数链接

$("a[@href^='google.com']:even")

现在,如需进一步使用jQuery元素选择返回的结果,你有两种方式。第一,你可以运行$("expression").get()来获取匹配元素的列表——这跟cssQuery完全一致。第二,你可以使用jQuery内置的特殊函数来操作CSS和DOM。所以,回到使用cssQuery为指向Google的链接加边框的例子上,你现在就可以这么做:

// 为所有指向Google的链接增加边框

$("a[@href^=google.com]").css("border","1px dashed red");

你可以从jQuery项目网站上找到大量的例子、演示和文档等,此外,还有可定制的下载:http://jquery.com/。

注意 应该指出的是,cssQuery或jQuery实际上并不只是能定位HTML文档而已,它们可以在任何XML文档上使用。至于纯粹的XML形式定位,请继续阅读下面的XPath部分。

5.4.3 XPath

XPath表达式是一种不可思议的定位XML文档的强大的方式。自问世几年来,几乎可以肯定DOM实现的背后必有XPath。尽管相对冗长,但XPath表达式比起CSS选择器来,能做的事情更多也更强大。表5-1并行比较了一些CSS选择器和XPath表达式的某些不同。

表5-1 CSS 3选择器与XPath表达式的比较

目  标

CSS 3

XPath

所有元素

*

//*

所有<p>元素

p

//p

所有子元素

p> *

//p/*

由ID获取元素

#foo

//*[@id='foo']

由类获取元素

.foo

//*[contains(@class, 'foo')]

由特性(attribute)获取元素

*[title]

//*[@title]

<p>的第一个子元素

p >*:first-child

//p/*[0]

所有拥有子元素的<p>

不支持

//p[a]

下一个元素

p + *

//p/下一兄弟元素::*[0]

如果前面这些表达式激发了你的兴趣,推荐你浏览XPath的两个规范(尽管现代浏览器通常只完全支持XPath 1.0)以初步了解它们是如何工作的:

l    XPath 1.0:http://www.w3.org/TR/xpath/。

l    XPath 2.0:http://www.w3.org/TR/xpath20/。

如果需要深入这个主题,我推荐你阅读O’Reilly出版的由Elliotte Harold和Scott Means所著的XML in a Nutshell2004),或者Apress出版的由Jeni Tennison所著的Beginning XSLT 2.0: From Novice to Professional2005)。此外,还有一些精彩的教程帮助你学习使用XPath:

l    W3Schools的XPath教程:http://w3schools.com/xpath/。

l    ZVON XPath 教程:http://zvon.org/xxl/XPathTutorial/General/examples.html。

目前,浏览器对XPath的支持各不相同:IE和Mozilla都比较完整(虽然不一样)地支持XPath实现,而Safari和Opera的版本还在开发中。作为补救,有几种完全使用JavaScript写的XPath实现方法。虽然它们通常会比较慢(跟基于浏览器的实现相比),但可以确保所有现代浏览器都能稳定运行:

l    XML for Script:http://xmljs.sf.net/。

l    Google AJAXSLT:http://goog-ajaxslt.sf.net/。

此外,一个名为Sarissa的项目(http://sarissa.sf.net/)打算为各种浏览建立一个通用的实现包装。它可以让你一次写成XML访问代码,同时仍能从支持的浏览器中获得更快的运行速度。这项技术的最大问题在于,Opera和Safari浏览器对XPath支持仍不足,走不出XPath先前实现的困境。

使用浏览器内置的XPath与使用得到广泛支持的纯粹的JavaScript解决方案比起来,通常被认为是试验性质的技术。尽管如此,XPath的使用和普及渐渐成长起来,可把它当作CSS选择器强有力的竞争对手。

现在你已经掌握了定位任意DOM元素或任意DOM元素集合的必要知识和工具,那么我们现在应该利用这些知识了:从特性的操作到增加和删除DOM元素。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论