IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  XML | Java technology  >

高级 XQuery:创建自定义函数

将软件开发的最佳实际添加到 XQuery 表达式

developerWorks
前一页第 4 页,共 10 页后一页

文档选项

样例代码


对本教程的评价

帮助我们改进这些内容


如何实现价格标签?

XQuery 函数还有其他用法吗?再看一看 清单 9 中的输出。注意,没有显示每种诱饵的价格。用户在 eCommerce 站点上购买诱饵可能是因为它提供便宜的价格。因此,要创建一个显示价格的函数。

现在您可能会问自己 “为什么需要这个函数?我可以将它从 XML 文件提取出来并显示它吗?”要记得 fishinhole.com 是国际性的,它在全球范围内做交易。因此显示的价格要符合特定国家的币种面值。如果您再次看看这个 XML,将发现它已经带有 <international-prices> 元素。

因此,在下一个用例中,要根据特定的国家确定每个产品的价格。这涉及到更改 Java 类和 XQ 文件,但不要更改 XML,因为它已经包含国际价格,如 清单 10 所示。


清单 10. 更改 Java 类
					
private static final String COUNTRY	= "Mexico";
private static final String COUNTRY_FIELD	= "country";
...
private String getAllMinnowsWithMaximumDelay(int maximumDelay) throws Exception {
	XQExpression expression = getGenericExpression(); 
	
	expression.bindInt(new QName(SHIPPING_DELAY_FIELD), SHIPPING_DELAY_IN_DAYS,
		conn.createAtomicType(XQItemType.XQBASETYPE_INTEGER));
	
	expression.bindInt(new QName(MAXIMUM_DELAY_FIELD), maximumDelay,
		conn.createAtomicType(XQItemType.XQBASETYPE_INTEGER));
	
	expression.bindString(new QName(COUNTRY_FIELD), COUNTRY,
		conn.createAtomicType(XQItemType.XQBASETYPE_STRING));
	
	FileReader fileReader = new FileReader(GET_ALL_MINNOWS_WITH_MAX_DELAY_FILE);
	XQSequence results = expression.executeQuery(fileReader);
	
	return results.getSequenceAsString(new Properties());
}

清单 10 与之前创建的 Java 类不同,因为它包含了两个新的静态字段和一个附加的表达式绑定。两个新的字段分别是特定国家的字段名和这个国家的实际名称。在这个示例中,测试用户居住在墨西哥,因此用户期望看到以比索显示的价格。这个新的表达式绑定将字段名(country)绑定到用户的国家名(Mexico)。

清单 11 中的新 XQ 文件与 清单 8 中的 XQ 文件没有很大的区别,但是更改还是很显著的。


清单 11. 新的 XQ 文件
					declare variable $docName as xs:string external;
declare variable $maximumDelay as xs:integer external;
declare variable $shippingDelay as xs:integer external;
declare variable $country as xs:string external;

declare function local:calculateReceivedIn($delay as xs:integer) 
{
	let $receivedIn := ($delay + $shippingDelay)
	return ($receivedIn)
}; 

declare function local:getPrice($minnowElement as element(minnow)) as xs:string
{
if ($country = 'Mexico') then
(concat((data($minnowElement/international-prices/price[@denomination="peso"]))
  ," Pesos"))

else if ($country = 'Canada') then 
(concat(
 (data($minnowElement/international-prices/price[@denomination="canadian-dollar"]))
  ," Canadian Dollars"))

else if ($country = 'United States') then
(concat((data($minnowElement/international-prices/price[@denomination="dollar"]))
 ," Dollars"))

else 
(concat((data($minnowElement/international-prices/price[@denomination="euro"]))
 ," Euros"))
};

for $minnows in doc($docName)//minnows
return
<div class="filterResults">
 <div class="brand">
	Brand: {data($minnows/@brand)}	
 </div>
 <div class="size">
	Size: {data($minnows/@size)} inches
 </div>
 {
 for $minnow in $minnows/minnow
 where $minnow/availability/shipping/delay<=$maximumDelay
 return
  <div class="singleFilterResult">
   <div class="color">
	Color: {data($minnow/@color)}
   </div>
   <div class="shippingInfo">
    <div class="receivedIn">
     Received in {local:calculateReceivedIn($minnow/availability/shipping/delay)} day(s)
    </div>
    <div class="price">
     {local:getPrice($minnow)}
    </div>
   </div>
  </div>
 }
</div>

首先,您需要声明新的变量 $country。在前一个清单中就将它与值 Mexico 绑定在一起。

接下来,您将声明新的函数 getPrice。这个函数有几个需要注意的地方。首先,它采用 element 数据类型。这与前一个函数不同,后者采用简单的数据类型(integer)。这是一个很好的示例,因为它演示了不仅可以传入简单类型作为函数的参数,也可以传入元素作为参数。

这个函数需要注意的第二个地方是您指定一个返回类型。在这个例子中,返回一个字符串。因此,您不再需要在函数的主体中使用单词 return。它表明这就是返回的内容。

函数体中使用 if/then 语句,并且将 $country 的值与该应用程序支持的其他国家进行比较。如果匹配,将以所在国家的货币面值返回这个产品的价格。默认的币种是欧元。

最后,主 XQuery 表达式拥有一个新的 div 标记,它在迭代时获取当前产品的价格。此时,将调用 getPrice 函数。它将自身(即整个 <minnow> 元素)作为一个参数传入。

这个教程的代码示例分别包含针对这个示例和前一个示例的文件。这个示例的文件是 XQueryFunctionTesterIncludesPrice.java,而上一个相应的 XQ 文件是 getAllMinnowsWithMaxDelayIncludesPrice.xq。

因此,像以前一样,编译并运行 XQueryFunctionTesterIncludesPrice。执行完毕时,输出结果应该类似于 清单 12


清单 12. 新 XQ 文件的输出
					
<div class="filterResults">
 <div class="brand">
  Brand: Yohuri
 </div>
 <div class="size">
  Size: 3 inches
 </div>
 <div class="singleFilterResult">
  <div class="color">
   Color: midnight blue
  </div>
  <div class="shippingInfo">
   <div class="receivedIn">
	Received in 3 day(s)
   </div>
  </div>
  <div class="price">
    100 Pesos
  </div>
 </div>
</div>

这次测试又成功了!因为您将国家配置为 Mexico,所以将看到以该国的货币面值显示的价格。在这个例子中货币单位为比索。您可以清楚地看到,price 类的 div 包含 100 Pesos 作为价格。在 XML 文档中,数字 100 也是正确的。





回页首



前一页第 4 页,共 10 页后一页
    关于 IBM 隐私条约 联系 IBM 使用条款