里列出了您在使用 XML 时应该尽量避免使用的技术。
Internet Explorer - XML 数据岛
它是什么?XML 数据岛是嵌入到 HTML 页面中的 XML 数据。
为什么要避免使用它?XML 数据岛只在 Internet Explorer 浏览器中有效。
用什么代替它?您应当在 HTML 中使用 JavaScript 和 XML DOM 来解析并显示 XML。
如需更多有关 JavaScript 和 XML DOM 的信息,请访问我们的 XML DOM 教程。
XML 数据岛实例
本例使用 XML 文档 "cd_catalog.xml"。
把 XML 文档绑定到 HTML 文档中的一个 <xml> 标签。id 属性定义数据岛的标识符,而 src 属性指向 XML 文件:
实例
本实例只适用于 IE 浏览器
<html>
<body>
<xml id="cdcat" src="cd_catalog.xml"></xml>
<table border="1" datasrc="#cdcat">
<tr>
<td><span datafld="ARTIST"></span></td>
<td><span datafld="TITLE"></span></td>
</tr>
</table>
</body>
</html>
<table> 标签的 datasrc 属性把 HTML 表格绑定到 XML 数据岛。
<span> 标签允许 datafld 属性引用要显示的 XML 元素。在这个实例中,要引用的是 "ARTIST" 和 "TITLE"。当读取 XML 时,会为每个 <CD> 元素创建相应的表格行。
Internet Explorer - 行为
它是什么?Internet Explorer 5 引入了行为。行为是通过使用 CSS 样式向 XML (或 HTML )元素添加行为的一种方法。
为什么要避免使用它?只有 Internet Explorer 支持 behavior 属性。
使用什么代替它?使用 JavaScript 和 XML DOM(或 HTML DOM)来代替它。
实例 1 - 鼠标悬停突出
下面的 HTML 文件中的 <style> 元素为 <h1> 元素定义了一个行为:
<html>
<head>
<style type="text/css">
h1 { behavior: url(behave.htc) }
</style>
</head>
<body>
<h1>Mouse over me!!!</h1>
</body>
</html>
下面显示的是 XML 文档 "behave.htc"(该文件包含了一段 JavaScript 和针对元素的事件句柄):
<attach for="element" event="onmouseover" handler="hig_lite" />
<attach for="element" event="onmouseout" handler="low_lite" />
<script>
function hig_lite()
{
element.style.color='red';
}
function low_lite()
{
element.style.color='blue';
}
</script>
实例 2 - 打字机模拟
下面的 HTML 文件中的 <style> 元素为 id 为 "typing" 的元素定义了一个行为:
<html>
<head>
<style type="text/css">
#typing
{
behavior:url(typing.htc);
font-family:'courier new';
}
</style>
</head>
<body>
<span id="typing" speed="100">IE5 introduced DHTML behaviors.
Behaviors are a way to add DHTML functionality to HTML elements
with the ease of CSS.<br /><br />How do behaviors work?<br />
By using XML we can link behaviors to any element in a web page
and manipulate that element.</p>v </span>
</body>
</html>
下面显示的是 XML 文档 "typing.htc":
<attach for="window" event="onload" handler="beginTyping" />
<method name="type" />
<script>
var i,text1,text2,textLength,t;
function beginTyping()
{
i=0;
text1=element.innerText;
textLength=text1.length;
element.innerText="";
text2="";
t=window.setInterval(element.id+".type()",speed);
}
function type()
{
text2=text2+text1.substring(i,i+1);
element.innerText=text2;
i=i+1;
if (i==textLength)
{
clearInterval(t);
}
}
</script>
如您还有不明白的可以在下面与我留言或是与我探讨QQ群308855039,我们一起飞!
一篇我们介绍了如何解析CSV和JSON数据:如何解析互联网数据:CSV和JSON篇,今天我们将介绍如何解析HTML和XML数据。
今天的介绍能够帮助你轻而易举地从网页中(比如下面的中航电子的2017年一季度交易数据)提取自己想要的数据:
准备
在Python中可以解析html和xml数据的软件包很多,今天我们介绍的是lxml,先安装:
$ pip install lxml
如果不熟悉pip的使用,可以参考另一篇文章:如何管理python软件包。
解析HTML数据
首先,回顾一下HTML的一些基本概念:
标签/tag:比如<html>, <h1>, <head>...一般成对出现,例如开始标签<html>和结束标签</html>
元素/element:开始标签到结束标签整段代码,标签对之间的即为内容(content)
属性/attribute:标签可拥有key=value形式的属性,比如<div class="header">...</div>
简单地理解,HTML网页就是由一组元素构成的一个集合。另外,大多数HTML标签是可以嵌套的,因此元素可以包含一系列子元素。有了这些概念做基础,我们将能够很容易理解软件包lxml的使用。实际上,在lxml里面,每个HTML元素对应一个lxml.html.HtmlElement对象,该对象提供一组标准的方法取访问包含在该元素内部的数据,比如属性、内容和子元素等。
例子
考察下面的链接,它提供中航电子在2017年第一季度的交易数据,我们打算从里面提取一些数据:
>>> url = "http://quotes.money.163.com/trade/lsjysj_600372.html?year=2017&season=1"
先把该网页爬取下来:
>>> import urllib2
>>> rsp = urllib2.urlopen(url).read()
>>> print rsp[0:15]
<!DOCTYPE html>
将字符串rsp转换成HtmlElement对象:
>>> from lxml import html
>>> doc = html.document_fromstring(rsp)
>>> type(doc)
<class 'lxml.html.HtmlElement'>
>>> doc.tag
'html'
所以其实doc就是一个html元素,它包含一些元素,比如head, body, link, div...
比如,如果你想提取该网页里面所有的链接(links):
>>> links = [ link for link in doc.iterlinks() ]
>>> len(links)
106
>>> links[0]
(<Element link at 0x1029179f0>, 'href', 'http://img1.cache.netease.com/f2e/finance/gegu/s.1064000.css', 0)
>>> links[0][2]
'http://img1.cache.netease.com/f2e/finance/gegu/s.1064000.css'
如果你想查看元素直接包含哪些子元素,可以调用getchildren()方法:
>>> doc.getchildren()
[<Element head at 0x10299a0a8>, <Element body at 0x10299a470>]
对嵌套很深的元素,如果熟悉xpath表达式,最直接的办法是调用xpath(...)方法:
>>> [ td.text for td in doc.xpath('/html/body/div[2]/div[4]/table/tr[1]/td')]
['2017-03-31', '19.02', '19.50', '19.02', '19.30', '0.36', '1.90', '102,212', '19,747', '2.53', '0.58']
此外,还可以通过find, findall, find_class, get_element_by_id等方法查找目标元素,比如:
>>> [ td.text for td in doc.findall('./body/div[2]/div[4]/table/tr[1]/td')]
['2017-03-31', '19.02', '19.50', '19.02', '19.30', '0.36', '1.90', '102,212', '19,747', '2.53', '0.58']
如果元素有属性,提取属性值也很方便,比如:
>>> form = doc.forms[0]
>>> form.tag
'form'
>>> form.attrib
{'action': '/trade/lsjysj_600372.html', 'id': 'date'}
>>> form.keys()
['id', 'action']
>>> form.get('action')
'/trade/lsjysj_600372.html'
>>> form.items()
[('id', 'date'), ('action', '/trade/lsjysj_600372.html')]
'>>> form.form_values()
[('year', '2017'), ('season', '1')]
>>> form.method
'GET'
做为一个完整的例子,下面的脚本就是爬取中航电子在2017年第一季度的数据:
输出效果:
(test) $ head -3 600372.csv
日期;开盘价;最高价;最低价;收盘价;涨跌额;涨跌幅(%);成交量(手);成交金额(万元);振幅(%);换手率(%)
2017-03-31;19.02;19.50;19.02;19.30;0.36;1.90;102,212;19,747;2.53;0.58
2017-03-31;19.02;19.50;19.02;19.30;0.36;1.90;102,212;19,747;2.53;0.58
解析xml数据
xml的格式和HTML类似,也是由标签构成的,但是要比HTML文件简单许多,看下面的xml文件片段处理:
>>> xmlstr="""\
... <target name="run" depends="jar">
... <java fork="true" classname="${main-class}">
... <classpath>
... <path refid="classpath"/>
... <path refid="application"/>
... </classpath>
... </java>
... </target>"""
>>> from lxml import etree
第一步是获取根节点:
>>> root = etree.fromstring(xmlstr)
>>> root.tag
'target'
如果要提取节点属性:
>>> root.items()
[('name', 'run'), ('depends', 'jar')]
>>> root.keys()
['name', 'depends'
>>> root.get("name")
'run'
>>> root.values()
['run', 'jar']
可以使用find, xpath等方法去获取和查找子节点:
>>> java = root.find("./java")
>>> java.tag
'java'
>>> java.keys()
['fork', 'classname']
>>> [ path.get("refid") for path in root.xpath("//path")]
['classpath', 'application']
lxml软件的功能很强大,如果有兴趣进一步了解,可以查看官方文档:
http://lxml.de/index.html
今天就写这么,欢迎大家留言、评论和关注。
文将详细介绍Spring Bean配置的三种不同方式的特点与使用条件。
主要包括:
一.基于XML的配置
请看Spring学习(十二)Spring 的配置文件概述
二.基于注解的配置
Spring2.0开始引入基于注解的配置方式,即Bean的定义信息可以通过在Bean的实现类上标注注解实现。
具体关于注解的知识请看Java注解(Annotation)介绍
@Component是Spring容器中的基本注解,表示容器中的一个组件(bean),可以作用在任何层次,下面的示例介绍该注解的使用方法。
注解配置示例:
他等效于XML配置
<bean id="userDao" class="cn.lovepi.***.userDao"/>
此外,还有一些其他的可以被用来注解bean的注解,这些可以让注解类本身的用途更加清晰,此外,特定的注解也具备特定的功能。
Spring在2.5后提供了一个context的命名空间,它提供了通过扫描类包来加载利用注解定义的Bean的方式。
在context中可以使用resource-pattern来过滤出特定的类。
<context:component-scan base-package="cn.lovepi.spring" resource-pattern="anno/*.class"/>
默认情况下加载的是package下的*.class即扫描全部类,在使用了resource-pattern之后,则只扫描package下的anno子包下的所有类。
不过使用resource-pattern并不能提供给我们完善的功能,所有我们得使用过滤子元素的方法。
其中:
include-filter表示要包含的目标类,
exclude-filter表示要排除在外的目标类
一个component-scan标签下可以有多个include-filter和exclude-filter,
过滤表达式所支持的类型如下表所示:
在这些类型当中,除了Custom外,aspectj的过滤功能最强大,他能轻易的实现其他类别的过滤规则。
Spring3.0提供了一系列的针对依赖注入的注解,这使得Spring IoC在XML文件之外多了一种可行的选择,主要包含如下注解类型:
1.Bean的定义注解
Spring自2.0开始,陆续引入了一些注解用于简化Spring的开发。
@Repository注解便属于最先引入的一批,用于将数据访问层(DAO层)的类标识为Spring Bean。具体使用如下:
①首先使用@Repository将DAO类声明为Bean
②在XML配置文件中启动Spring的自动扫描功能
如此的话,我们便不在需要在XML当中显式使用bean来进行bean的配置。Spring容器在初始化的时候便会自动扫描base-package所指定的包以及子包下面的所有class文件。所有标注为Repository的类将被自动注册为bean。
为什么Repository只能标注在DAO类上面呢?
因为该注解的作用不只是将类识别为bean,同时他还能将所标注的类中所抛出的数据访问异常封装为Spring的数据访问异常类型。Spring本身提供了一个丰富的,并且是与具体的访问技术无关的数据访问异常结构,用于封装不同的持久层框架所抛出的异常,使得异常独立与底层的框架。
Spring2.5在@Repository的基础上增加了功能类似的额外三个注解,总共有如下四种注解:
这三个注解除了作用于不同软件层次的类,其使用方式与Repository是完全相同的。
2.Bean的生命周期注解
在某些情况下,可能需要我们手工做一些额外的初始化或者销毁操作,例如资源的获取和是否操作,Spring1.x为此提供了两种方式供用户指定执行生命周期回调的方法:
示例如下:
在这里,我们指定了userService 这个bean的初始化方法为:init 销毁方法为:destory
Spring2.5在保留以上两种方式的基础上,提供了对JSR-250的支持。
JSR-250规范定义了两个用于指定声明周期方法的注解:
注解示例说明:
在这里init方法是初始化之后执行的方法,而destory方法为销毁之前执行的方法
由于使用了注解,所以得激活Bean的后处理器,所以得在XML配置文件当中增加
<context:annotation-config/>
3.Bean的依赖检查注解
Spring2.0之前使用dependency-check在配置文件中设置属性用于依赖检查(只会检查Setter方法是否被调用),缺点是粒度较粗,该属性的取值包括以下几种:
使用Spring2.0提供的@Required注解,提供了更细粒度的控制,@Required注解只能标注在Setter方法之上,(标注在其他方法之上会被忽略 )用于检查其是否被调用,当Setter方法未被调用的话会抛出异常。
由于使用了注解,所以得激活Bean的后处理器,所以得在XML配置文件当中增加
<context:annotation-config/>
4.Bean的自动装配注解
@Autowired可以对成员变量、方法和构造函数进行标注,来完成自动装配的工作,他根据类型进行自动装配,如果需要按名称进行装配,则需要配合@Qualifier使用。
当标注了@Autowired的方法所需的类型在Spring容器中不存在的话会抛出异常
如上面的例子所示,假如Spring容器中没有LogDao这个bean的话便会抛出异常。
解决的办法便是使用required=false属性来标注
但是假如Spring当中存在多个所需类型的bean,那么便要使用@Qualifier注解来指定名称。
@Autowired 可以对类中集合类的变量或方法入参进行标注,此时会将容器中类型匹配的所有Bean都注入进来,如下所示:
Spring会将容器中所有类型为Plugin的bean都注入到集合中去。
三.基于Java类的配置
基于Java类定义Bean配置元数据,其实就是通过Java类定义Spring配置元数据,且直接消除XML配置文件。
首先让我们看一下基于Java类如何定义Bean配置元数据,具体步骤如下:
接下来通过示例来演示下如何基于Java类来配置Spring
首先创建一个配置类
然后还需要一个测试类,来查看配置是否成功
通过@Configuration注解的类将被作为配置类使用,表示在该类中将定义Bean配置元数据,且使用@Configuration注解的类本身也是一个Bean,使用方式如下所示:
其中Configuration中的参数值即为该bean的名称。
通过@Bean注解配置类中的相应方法,则该方法名默认就是Bean名,该方法返回值就是Bean对象,并定义了Spring IoC容器如何实例化、自动装配、初始化Bean逻辑,具体使用方法如下:
其中name为bean的名称,可以有多个,autowire为是否自动装配,默认值为NO,initMethod为bean的初始化方法,destoryMethod为bean的销毁方法。
bean的注解具体使用如下:
如上的代码等价与XML配置:
注意:使用bean注解的方法不能是private、final、static的。
基于Java方式的配置方式不是为了完全替代基于XML方式的配置,两者可以结合使用,因此可以有两种结合使用方式:
引入基于XML配置文件:
可以看到在java程序中使用@ImportResource导入了XML的配置文件
引入基于Java的配置文件:
可以看到在XML的配置文件当中将java的配置类当中Bean来声明,第一行的是开启注解驱动支持。
值得注意的是必须得配置<context:annotation-config/>在XML配置文件中。
Spring提供了一个AnnotationConfigApplicanContext类,能够直接通过标注@Configuration的Java类启动Spring容器:
通过构造函数加载配置类:
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConf.class);
通过编码方式注册配置类:
可以看到ctx注册了多个configuration类,然后通过refresh类来刷新容器以应用这些配置文件。
可以通过代码一个个的引入配置类,当然也可以使用@Import注解来引入配置类
引入多个配置类:
总结:不同配置方式比较
我们来看一下不同配置方式在不同方面的使用
其实Spring支持这么多的配置方式,那么这些配置方式必然有其自己独特的舞台
基于XML的配置主要使用场景:
基于注解的配置主要使用场景:
基于Java类的配置主要使用场景:
在日常的开发中我们主要是使用XML配置和注解配置方式向结合的开发方式,一般不推荐使用基于Java类的配置方式。
*请认真填写需求信息,我们会在24小时内与您取得联系。