[XML]学习笔记(七)XPath&XQuery

XPath是在XML文档中查找信息的语言,可以在XML文档中对元素和属性进行遍历。XQuery和XPointer都是建立在XPath之上的。注意:只给出XPath,也可以返回该XPath下的所有节点的集合。


一、 XPath简介:
a) 使用路径表达式来选取XML文档中的节点或节点集,与文件系统的路径十分相似;
b) 含有100多个内建函数,可用于字符串值、数值、时间和日期比较等;
c) 属于XSLT标准中的主要元素;
d) 属于W3C标准。


二、 XPath节点:共七种,XML文档被当作节点树对待,树根称为文档节点/根节点。

<bookstore>
<book category="CHILDREN">
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>
</bookstore>

a) 元素:如<author>J K. Rowling</author>;

b) 属性:如lang="en";
c) 文本;
d) 命名空间;
e) 处理指令;
f) 注释;
g) 根节点。


三、 XPath节点关系:

a) Parent:父节点;
b) Children:子节点;
c) Sibling:同胞节点;
d) Ancestor:先辈节点;
e) Descendant:后代节点;
f) Preceding:当前节点的开始标签之前的所有节点;
g) Following:当前节点的开始标签之后的所有节点。
 
四、 基本值/原子值(Atomic value):无父节点或无子节点的节点,如元素的值J K. Rowling,属性的值"en"。


五、 项目:即基本值或节点。


六、 XPath语法:每个XPath表达式由若干个step组成,除了最后一个step每个都会返回一个set节点,而最后一个step可以返回number、boolean、字符串或node集合。


a) 选取节点:


i. nodename:选取当前节点的所有子节点,如bookstore,选取bookstore元素的所有子节点。


ii. /:从根节点开始选取。

1. 如/bookstore,选取bookstore作为根元素。
注:如果路径起始于/,则此路径始终代表到对应元素的绝对路径?
2. 如bookstore/book,选取bookstore子元素中的所有book元素。


iii. //:从匹配选择的当前节点选择文档中的节点,不考虑其位置。

1. 如//book,表示选取所有的book子元素,不考虑其在文档中的位置。
2. 如bookstore//book,选择bookstore后代中的所有book元素。


iv. .:选取当前节点,相当于self::。


v. ..:选取当前结点的父节点,相当于parent::。


vi. @:选取属性。如//@lang,表示选取所有lang属性。


b) 谓词(Predicates):嵌在方括号中,用于查找某个特定的/包含某个特定值得节点。

i. /bookstore/book[1]:选取bookstore子元素中的第一个book元素;
/bookstore/book[last()]:选取bookstore子元素中的最后一个book元素;
/bookstore/book[position()<3]:选取bookstore子元素中的前两个book元素;
ii. //title[@lang]:选取所有含有lang属性的title元素;
//title[@lang=’eng’]:选取所有lang属性为eng的title元素。
iii. /bookstore/book[price>35.00]/title:选取bookstore下price高于35.00的book的title元素。
iv. /book/price/text():取book的子元素price的文本内容。
v. count()怎么用?如何计数papar下的所有title?
 
c) 通配符:*匹配任何节点元素;
i. 如/bookstore/*,表示选取bookstore元素的所有子元素。
ii. 如//*,表示选取文档中的所有元素。
iii. 如//title[@*],表示选取所有带属性的title元素。


d) 选取多条路径:|

i. //book/title | //book/price:选出所有book元素的title和price?选取 book 元素的所有 title 和 price 元素?
ii. //title | //price:选出文档中所有title元素和price元素。
iii. /bookstore/book/title | //price:选出bookstore中子元素为book的所有title子元素和所有文档中的所有price元素。


七、 XPath轴(Axes):用于定义相对于当前节点的节点集。位置路径可以是绝对的(以/开始)也可以是相对的(以元素/节点开始),每个/分隔一个step。

a) Step:语法——axisName::nodeTest[predicate]
i. axis:定义所选节点与当前节点之间的树状关系。
ii. nodeTest:识别轴内部的节点。
iii. predicate:0个或多个,用于筛选所选节点集。
例:
i. child::book:选取所有属于当前节点的子元素的book节点。
ii. attribute::lang:选取当前节点的 lang 属性。
iii. child::*:选取当前节点的所有子元素。
iv. attribute::*:选取当前节点的所有属性。
v. child::text():选取当前节点的所有文本子节点。
vi. child::node():选取当前节点的所有子节点。
vii. descendant::book:选取当前节点的所有book后代。
viii. ancestor::book:选择当前节点的所有book先辈。
ix. ancestor-or-self::book:选取当前节点的所有book先辈以及当前节点(如果此节点是 book 节点)
x. child::*/child::price:选取当前节点的所有 price 孙节点。
注:child::相当于空轴名,如/root/paper=/child::root/child::paper

绝对路径:


 
相对路径:
 


XQuery:“XQuery与XML的关系好比SQL与数据库的关系”,它被设计用来查询XML数据,建立在XPath表达式之上,被所有主要的数据库引擎支持(Oracle,Microsoft,IBM等)。
考虑books.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>


<bookstore>


<book category="COOKING">
  <title lang="en">Everyday Italian</title>
  <author>Giada De Laurentiis</author>
  <year>2005</year>
  <price>30.00</price>
</book>


<book category="CHILDREN">
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>


<book category="WEB">
  <title lang="en">XQuery Kick Start</title>
  <author>James McGovern</author>
  <author>Per Bothner</author>
  <author>Kurt Cagle</author>
  <author>James Linn</author>
  <author>Vaidyanathan Nagarajan</author>
  <year>2003</year>
  <price>49.99</price>
</book>


<book category="WEB">
  <title lang="en">Learning XML</title>
  <author>Erik T. Ray</author>
  <year>2003</year>
  <price>39.95</price>
</book>


</bookstore>



一个比较简单的例子:

doc("books.xml")/bookstore/book[price>35]/count(author)

查询结果:5 1
即所有价格大于35的书的作者数量。
一、 XQuery基本语法规则:
a) 对大小写敏感;
b) 元素、属性及变量必须是合法的XML名称;
c) 字符串可使用单引号或双引号;
d) 变量由$name定义;
e) 注释格式:(:注释内容:)。
二、 XQuery语法:
a) 条件表达式:If-Then-Else,其中If和Else是必须的,Then可有可无。
如:

for $x in doc("books.xml")/bookstore/book
return if ($x/@category="CHILDREN")
	then <child>{data($x/title)}</child>
	else <adult>{data($x/title)}</adult>

查询结果如下:

<adult>Everyday Italian</adult>
<child>Harry Potter</child>
<adult>Learning XML</adult>
<adult>XQuery Kick Start</adult>

b) 比较操作:

i. 通用比较:=, !=, <, <=, >, >=。
如:$bookstore//book/@q > 10,如果属性q的值大于10,则表达式的返回值为true。
ii. 值比较:eq, ne, lt, le, gt, ge。
如:如果返回的属性q有且只有1个且值大于10,则返回true;如果返回的属性q有多个,则发生错误。
三、 XQuery高级语法:
a) 添加元素和属性:
i. 添加元素和文本:
<ul>
{
for $x in doc("books.xml")/bookstore/book
order by $x/title
return <li>{data($x/title)}. Category: {data($x/@category)}</li>
}
</ul>


查询结果:

<ul>
<li>Everyday Italian. Category: COOKING</li>
<li>Harry Potter. Category: CHILDREN</li>
<li>Learning XML. Category: WEB</li>
<li>XQuery Kick Start. Category: WEB</li>
</ul>

ii. 添加属性:使用class添加属性

<ul>
{
for $x in doc("books.xml")/bookstore/book
order by $x/title
return <li class="{data($x/@category)}">{data($x/title)}</li>
}
</ul>


查询结果:

<ul>
<li class="COOKING">Everyday Italian</li>
<li class="CHILDREN">Harry Potter</li>
<li class="WEB">Learning XML</li>
<li class="WEB">XQuery Kick Start</li>
</ul>


b) FLWOR表达式:FLWOR即For, Let, Where, Order by, Return。
上面的例子可表示为:

for $x in doc("books.xml")/bookstore/book
where $x/price>35
return $x/count(author)


i. 加标签:

xquery version "1.0";
<ul>
{
for $x in doc("books.xml")/bookstore/book
where $x/price>35
return <li>{$x/count(author)}</li>
}
</ul>


查询结果:

<ul>
<li>5</li>
<li>1</li>
</ul>


ii. data()去除元素标签,只显示内部数据:
<ul>
{
for $x in doc("books.xml")/bookstore/book/title
order by $x
return <li>{data($x)}</li>
}
</ul>


查询结果:
<ul>
<li>Everyday Italian</li>
<li>Harry Potter</li>
<li>Learning XML</li>
<li>XQuery Kick Start</li>
</ul>


iii. for语句:将变量$x绑定到in表达式中返回的每个项目中。in表达式中使用关键字to可限定循环次数,使用关键字at可计算循环次数。对于含有多个in表达式的,使用逗号分隔它们,循环次数为多个in表达式可取项目的组合数。
如:
at关键字:

for $x at $i in doc("books.xml")/bookstore/book/title
return <book>{$i}. {data($x)}</book>


查询结果:变量i记录了循环的次数

<book>1. Everyday Italian</book>
<book>2. Harry Potter</book>
<book>3. XQuery Kick Start</book>
<book>4. Learning XML</book>

多循环变量:

for $x in (10,20), $y in (100,200)
return <test>x={$x} and y={$y}</test>

查询结果:

<test>x=10 and y=100</test>
<test>x=10 and y=200</test>
<test>x=20 and y=100</test>
<test>x=20 and y=200</test>

循环嵌套:

for $x1 in doc("books.xml")/bookstore
return for $x2 in $x1/book
return $x2/price

等价于:

for $x2 in (for $x1 in doc("books.xml")/bookstore
return $x1/book)
return $x2/price


查询结果:

<price>30.00</price>
<price>29.99</price>
<price>49.99</price>
<price>39.95</price>


iv. let语句:用于变量分配,迭代产生中间结果,与for的区别:for会产生多个绑定,而let只产生一次绑定。而且let中没有at关键字。
如:

let $x :=doc("books.xml")/bookstore/book/title
return <book>{data($x)}</book>

查询结果:

<book>
Everyday ItalianHarry
PotterXQuery
Kick
StartLearning XML
</book>

v. where语句:用于过滤绑定的结果,后面常跟条件表达式。

for $x in doc("books.xml")/bookstore/book
where $x/price>30 and $x/price<100
return $x


查询结果:

<book category="WEB">
<title lang="en">XQuery Kick Start</title>
<author>James McGovern</author>
<author>Per Bothner</author>
<author>Kurt Cagle</author>
<author>James Linn</author>
<author>Vaidyanathan Nagarajan</author>
<year>2003</year>
<price>49.99</price>
</book>
<book category="WEB">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>


vi. order by语句:用于将结果排序,可以通过order_spec=ascending/descending来指定升序(默认)还是降序。注意:order by默认按指定元素升序排列,但不含order by的查询并不表示将按升序排列。
如:
for $x in doc("books.xml")/bookstore/book
where $x/price>30 and $x/price<100
order by $x/price descending
return $x


vii. return语句:规定要返回的内容。
c) XQuery用户定义函数:
i. 语法:
declare function 前缀:函数名($参数 as 数据类型)
  as 返回的数据类型
{


(: ...函数代码... :)


};
如下面的例子中:
declare function local:minPrice(
  $price as xs:decimal)
  as xs:decimal
{
let $disc :=($price) div 100
return ($price - $disc)
};
for $x in doc("books.xml")/bookstore/book
return <minPrice>{local:minPrice($x/price)}</minPrice>


查询结果如下:
<minPrice>29.7</minPrice>
<minPrice>29.6901</minPrice>
<minPrice>49.4901</minPrice>
<minPrice>39.5505</minPrice>


四、 利用XQuery将XML转化成HTML的例子:
源XML文档即books.xml,目标html的显示效果为:
 

目标html为:

<html>
	<head><title>Book List</title></head>
	<body>
		<h1>Book List</h1>
		<table border="1" cols="3" width="100%">
			<tbody>
			<tr>
				<td><year>2005</year></td>
				<td><author>Giada De Laurentiis</author></td>
				<td><price>30.00</price></td>
			</tr>
			<tr>
				<td><year>2005</year></td>
				<td><author>J K. Rowling</author></td>
				<td><price>29.99</price></td>
			</tr>
			<tr>
				<td><year>2003</year></td>
				<td><author>James McGovern</author>
					<author>Per Bothner</author>
					<author>Kurt Cagle</author>
					<author>James Linn</author>
					<author>Vaidyanathan Nagarajan</author>
				</td>
				<td><price>49.99</price></td>
			</tr>
			<tr>
				<td><year>2003</year></td>
				<td><author>Erik T. Ray</author></td>
				<td><price>39.95</price></td>
			</tr>
			</tbody>
		</table>
	</body>
</html>



转换的XQuery为:
xquery version "1.0";
<html>
	<head><title>Book List</title></head>
	<body>
		<h1>Book List</h1>
		<table border="1" cols="3" width="100%">
			<tbody>
			{
			for $x in doc("books.xml")/bookstore/book
				return <tr>
					<td>{$x/year}</td>
					<td>{$x/author}</td>
					<td>{$x/price}</td>
				</tr>
			}			
			</tbody>
		</table>
	</body>
</html>


五、 利用XQuery实现XML之间的转换:
原XML文档:
<company>
	<div no="7a">
		<dept no="42">
			<emp no="123456" name="Whoptimone, Ida"/>
			<emp no="654321" name="Tirebiter, George"/>
		</dept>
		<dept no="51">
			<emp no="832953" name="Danger, Nick"/>
		</dept>
	</div>
	<div no="2b">
		<dept no="57">
			<emp no="283412" name="Boss, Yuda"/>
		</dept>	
	</div>
</company>


目标XML文档:


 

转换XQuery文档:

xquery version "1.0";
<company>
{
	for $div in doc("company.xml")/company/div
		return for $dept in $div/dept
			return for $emp in $dept/emp
				return <employee id="{data($emp/@no)}">
					<name>{data($emp/@name)}</name>
					<division>{data($div/@no)}</division>
					<department>{data($dept/@no)}</department>
				</employee>
}
</company>

(:<company>
{
for $emp in doc("company.xml")//emp
	 return <employee id="{data($emp/@no)}">
	            <name>{data($emp/@name)}</name>
	            <division>{data($emp /../../@no)}</division>
	            <department>{data($emp /../@no)}</department>
             </employee>
}
</company>:)






<think>好的,我需要回答用户关于如何在JMeter中使用XPath查询提取数据的问题。首先,我需要回忆一下JMeter的XPath Extractor的使用步骤和相关配置。根据用户提供的引用内容,特别是引用[1]、[2]、[3],应该包括添加XPath Extractor的位置、配置参数、XPath表达式写法以及注意事项。 首先,用户需要知道如何添加XPath Extractor。根据引用[3],正确的路径是测试计划 -> 线程组 -> HTTP请求 -> 右键添加 -> 后置处理器 -> XPath提取器。这部分需要详细说明步骤,确保用户能找到正确的位置。 接下来是配置参数部分。引用[1]提到要确保HTTP响应的Content-Type是text/xml或application/xml,否则JMeter无法处理。因此,需要强调这一点,并说明在XPath Extractor界面中需要填写的字段,比如变量名称、XPath表达式、默认值等。引用[2]中的例子展示了如何提取XML中的文本内容,比如使用//user/name/text()来获取名字,这个例子可以用来具体说明XPath表达式的编写方法。 然后,注意事项也很重要。比如,XPath的正确性验证,可能需要使用在线工具测试表达式是否正确。同时,要提到如何处理命名空间的问题,如果XML中有命名空间,可能需要使用local-name()函数来忽略命名空间前缀,如//*[local-name()='user']/name。此外,引用[1]还提到了变量在后续请求中的使用方式,比如${var},这部分需要说明如何引用提取到的变量。 另外,可能需要补充一些常见问题,比如性能考虑,因为复杂的XPath表达式可能会影响测试性能,所以建议尽量简化表达式。或者如何处理多个匹配项的情况,比如匹配数字的设置,用户可能需要提取多个元素,这时候需要说明匹配数字的作用,以及如何结合变量使用。 最后,总结步骤,确保用户能够按照流程操作,并正确应用XPath查询提取数据。同时,生成相关问题,帮助用户进一步学习,比如如何处理非XML响应,或者如何结合正则表达式提取器等。 需要检查是否有遗漏的要点,比如是否提到了变量作用域,或者是否需要配置JMeter的依赖库,比如确保XPath Extractor需要XML解析包,但根据引用内容,用户提供的资料中没有提到这点,可能不需要涉及。或者是否需要启用DTD验证,但同样,引用中没有提到,可能属于进阶内容,暂时不涉及。 综合以上思考,组织回答结构,确保符合用户的要求,使用中文,正确使用LaTeX格式,行内公式用$...$,独立公式用$$...$$,但在这个问题中可能用不到数学公式,所以主要注意其他格式要求,如代码块使用```python等,但这里可能用JMeter的配置界面截图,但用户示例中使用的是代码块,所以用代码块展示配置步骤中的各个参数设置。</think>在JMeter中使用XPath查询提取数据需要以下步骤: ### 一、添加XPath Extractor 1. 右键目标HTTP请求,选择 **添加 → 后置处理器 → XPath Extractor** [^3]。 2. 配置参数: - **名称**:自定义(如“提取用户名”) - **变量名称**:存储提取结果的变量(如`username`) - **XPath查询**:填写XPath表达式(例如提取XML中的用户名字段:`//user/name/text()`[^2]) - **默认值**:未匹配时的默认值(可选) - **匹配数字**:若有多条匹配结果,指定提取第几条(0表示随机) ### 二、编写XPath表达式 1. **基本语法**: - 从根节点定位:`/root/child`,如`//user/age`提取年龄。 - 通配符:`//*`匹配任意节点。 - 属性提取:`//user/@id`提取`id`属性值。 2. **处理命名空间**: - 若XML包含命名空间(如`<ns:user>`),需使用`local-name()`忽略前缀: ```xpath //*[local-name()='user']/name/text() ``` ### 三、注意事项 1. **响应格式验证**: - 确保HTTP响应头`Content-Type`为`text/xml`或`application/xml`[^1]。 - 若响应为HTML但包含XML片段,需手动设置JMeter的**响应数据格式**为XML。 2. **表达式验证**: - 使用在线工具(如[XPath测试器](https://www.freeformatter.com/xpath-tester.html))验证表达式正确性[^1]。 3. **变量调用**: - 在后续请求中通过`${变量名}`引用提取值(如`${username}`)。 ### 四、示例 假设响应数据为: ```xml <user> <name role="admin">Alice</name> <age>28</age> </user> ``` - 提取`name`文本:`//user/name/text()` → 变量`username`值为`Alice` - 提取`role`属性:`//user/name/@role` → 变量`user_role`值为`admin` ```java // JMeter的XPath Extractor配置示例(非代码,仅为参数说明) 名称:提取用户角色 变量名称:user_role XPath查询://user/name/@role 默认值:guest 匹配数字:1 ``` ### 五、性能优化建议 - 避免复杂XPath表达式(如多层嵌套或模糊查询),以减少解析开销。 - 若需提取多个字段,可添加多个XPath Extractor实例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值