如何实现价格标签?
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 也是正确的。
|