级别: 中级 Susan Malaika, 高级技术人员, IBM Jan-Eike Michels, 软件工程师, IBM Christian Pichler, Data Server Solutions(带薪实习), IBM
2009 年 2 月 05 日 XQuery 是面向 XML 的查询语言,它可以用于修改 XML。在本文中,学习修改存储在内存中或 DB2® pureXML™ 数据库中的 XML 的不同方式。在 4 个不同的 DB2 pureXML 用例中探索修改 XML 的不同方式:卫生保健、商业、金融衍生市场和信息技术。最后,研究关于何时使用 XQuery 执行子文档更新或全文档替换以及对存储的 XML 进行版本控制的指导原则。
简介
XML 越来越多地在不同的行业被作为消息交换格式。行业协会或政府常常会定义这些交换消息的结构。一些项目的日益流行正在鼓励使用这些 XML 交换消息。例如,这些项目包括信息即服务(Information as a Service)和软件即服务(Software as
a Service,SaaS),它们拥有诸如 Web 服务、文件传输协议(FTP)、消息传递、电子邮件和基于 Web 的提要信息等技术方面的优势。
组织在使用和生产这些交换消息的同时,也开始直接存储这些消息(例如,为了审计目的)。在某些系统中,这些存储的消息是支持机构或公司业务所需的最新信息的主要来源。
在某些情况下,需要修改存储的 XML 消息或者从已有的存储中的消息产生新的消息。产生新的 XML 消息的例子有:
- 关联到(“链接” 到)已有信息。例如,在卫生保健行业,可能产生附加的检查结果,所以要根据已有记录创建新的病人记录,然后用最新的医疗结果扩充已有记录。
- 合并附加的信息。例如,在商业领域,可能在随后将其他商品添加到一个订单中。通常,处理程序是取消原有的订单,并产生一个新订单,新订单中同时包含原有订单的内容和追加的订货。
- 包含修改后的信息。例如,在金融衍生市场中,可能通过一个约务更替(novation)过程在某个时间点上用新的一方替换已有的一方。
XQuery 是用于查询 XML 文档的语言,它已增加了支持在 XML 文档上执行子文档更新的扩展。通过这些扩展可以添加新节点、删除或重命名已有的节点以及替换已有的节点和它们的值(关于 XQuery 的更多信息,请参阅 参考资料)。
本文解释如何将 W3C 标准 XQuery Update Facility 应用到 DB2 中的 XML 上。然后,在 4 个行业 —— 卫生保健、商业、金融衍生市场和信息技术 —— 的上下文中演示 XQuery Update Facility。本文中的例子基于这些行业的典型消息交换格式。本文是对之前一篇题为 “Update XML in DB2
9.5”(developerWorks,2007 年 10 月)的文章的补充,那篇文章谈到了 XQuery 更新的基础,本文还展示使用 XQuery 修改 XML 比在应用程序中读取、解析和修改 XML 更加容易和高效。
如果想试用 XQuery 更新,可以下载一些行业包(Industry Bundles),它们是 DB2 pureXML 在线演示 “Industry Formats and Services with pureXML” 的一部分,可以免费使用(请参阅
参考资料)。
修改 XML 的方式
图
1 展示了修改和更新 XML 的不同方法,它们包括:
-
修改内存中的 XML:XML 被修改,但是这种修改不会永久保存。
-
修改磁盘上的 XML 并在原位置存储修改后的 XML:根据原始的 XML 创建一个修改后的 XML。然后存储修改后的 XML,而不是原始的 XML,从而替换原始的 XML。
-
修改磁盘上的 XML,并另外存储修改后的新的 XML:根据原始的 XML 创建一个修改后的 XML。然后另外存储这个修改后的版本,与原始版本区分开。
图 1. 修改和更新 XML 的不同方法
通过 XQuery 更新修改 XML 的使用模式
修改 XML 的方式是通过 XQuery 更新支持对 XML 执行更新的模式的基础。图 2 展示了不同的更新模式,它们包括:
- 更新存储在原处的 XML
- 插入修改后版本的 XML
- 根据一个 XML 请求(在内存中)动态更新 XML,以产生一个 XML 响应
- 通过一个 XQuery 更新视图隐藏 XML 内容的某些部分
图 2. XQuery 更新模式
更新存储在原处的 XML 和插入更新后版本的 XML 是持久化存储修改后的 XML 的两种主要方式。动态更新 XML 不会将 XML 请求或响应存储在数据库中,虽然它们是可以被存储的。通过 XQuery 更新视图隐藏 XML 内容的某些部分并不会修改存储的内容,而是允许利用传统的关系视图的安全特性。
接下来将更详细地描述每种模式。另外还有一些例子,这些例子假定 DB2 pureXML 数据库中已经有一个表,这个表有 2 个列或更多的列;其中一个列的类型是 XML。
更新存储在原处的 XML
更新存储在原处的 XML 意味着使用 XQuery Update 标记在原始的 XML 上执行子文档更新。
清单 1 展示了一个 SQL/XML 语句,其中有一个嵌入的 XQuery 更新语句,用于修改原始 XML 中的邮政编码,然后用修改后的 XML 替换原始的 XML:
清单 1. 用更新后的 XML 替换原始 XML 的 XQuery 更新
UPDATE xmlcustomer
SET info = XMLQUERY('transform
copy $new := $i
modify do replace value of $new/customerinfo/addr/zipcode
with 90111
return $new' PASSING info AS "i")
WHERE cid = 1000; |
插入修改后的 XML
更新已有的 XML 同时保留原始 XML 的另一种方法是插入一个完整的、新的、更新后的记录,使之与已有的、原始的 XML 共存。
清单 2 显示了一个 SQL/XML 语句,其中有一个嵌入的 XQuery 语句,用基于原始 XML 的修改过的 XML 插入一个新行:
清单 2. 在数据库中插入修改后的 XML 的 XQuery 更新
INSERT INTO xmlcustomer (cid,
info)
VALUES (1003,
XMLQUERY('transform
copy $new := $i
modify do replace value of $new/customerinfo/addr/zipcode
with 90111
return $new' PASSING (SELECT info
FROM xmlcustomer
WHERE cid=1000) as "i")); |
根据一个 XML 请求动态更新 XML 以产生一个 XML 响应
动态更新 XML 意味着当从一个 XML 变量或列中获得 XML 时,在内存中修改它。
清单 3 演示了一个 XQuery 语句,该语句在获得 XML 时动态地修改 XML 中的邮政编码:
清单 3. 在内存中产生修改后的 XML 的 XQuery 更新
XQUERY
for $doc in db2-fn:sqlquery('SELECT info
FROM xmlcustomer
WHERE cid=1000')
return transform
copy $new := $doc
modify do replace value of $new/customerinfo/addr/zipcode
with 90111
return $new; |
通过 XQuery 更新视图隐藏 XML 内容的某些部分
有时候,有必要对某些用户隐藏或掩盖 XML 的某些部分,例如对医务人员隐藏社会保险号,或者为了调查目的去掉敏感的客户信息。可以在 XML 上创建视图,应用 XQuery 更新隐藏或调整 XML 的某些部分。注意,应该仔细检查通过 XQuery 更新视图进行访问的性能。
清单 4 演示了如何通过 anonymousCust 视图对访问 XML 的软件隐藏客户姓名、街道、邮政编码和电话号码:
清单 4. 使用视图隐藏 XML 某些部分的 XQuery 更新
CREATE VIEW anonymousCust (custInfo)
AS SELECT XMLQUERY('for $ci in $i
return transform
copy $c := $i
modify (do delete $c/customerinfo/name,
do delete $c/customerinfo/addr/street,
do delete $c/customerinfo/addr/zipcode,
do delete $c/customerinfo/phone)
return $c' PASSING info AS "i")
FROM xmlcustomer; |
HL7 更新(版本控制和链接)
Health Level 7(HL7)是卫生保健行业医院临床和管理领域的一个标准开发组织(Standards Developing Organization,SDO)。HL7 基于
Reference Information Model(RIM),后者是一个信息模型,所有 HL7 的规范都源于这个模型。其中一个规范是 Clinical Document Architecture(CDA),该规范描述用于交换的临床文档的结构和语义。CDA 文档可以包含一个病人的姓名、地址、性别或用药等信息。
除了 CDA 文档中包含的结构和语义外,该规范还定义如何在已有的 CDA 文档上执行更新。下面是一个示例情景,在此情景下可以更新 CDA 文档:
病人 Megan Brown 不得不拜访当地的医师,因为她需要做血液检查。但是,在拜访医师时,Megan 并没有提供详细地址,而是在做完血液检查之后才提交了她的详细地址。
正如上面的例子所示,现在需要用 Megan 的地址更新 CDA 文档。为此可以更新 CDA 文档本身。但是,CDA 规范描述到,已有的 CDA 文档不能直接更新。相反,必须创建原始文档的一个副本,然后做出相应的更新。除了更新后的 CDA 文档的副本外,还必须将一个引用添加到更新后的文档中,该引用指向已有的、原始的 CDA 文档(要了解关于 CDA 的更多信息,请参阅 参考资料)。
图 3 演示了根据规范更新一个 CDA 文档:
图 3. 更新 CDA 文档的场景
每个 CDA 文档有一个元素
<id>,该元素为每个文档赋予一个惟一的标识符。CDA 文档的版本控制是通过元素 <setId> 和
<versionNumber> 完成的。原始文档和它的更新后的版本有相同的
<setId>,但是有不同的
<versionNumber>,其中
<setId> 表明这两个文档属于同一种文档,而
<versionNumber> 则表明版本。除了版本控制信息外,还有必要定义文档之间所谓的 “关系”。当一个原始文档被它的更新后的版本替换时,有必要定义一个关系,以表明该文档被另一个文档替换。这种关系的定义是通过元素
<relatedDocument> 实现的。
代码片段
清单 5 展示了一个已有的 CDA 文档的摘录,该文档包含病人的信息,但是缺少重要的联系方式:
清单 5. 原始 HL7 CDA 示例 XML 文档的摘录
...
<id root="2.16.840.1.113883.3.18.1" extension="2"/>
<setId root="2.16.840.1.113883.3.18.1" extension="2"/>
<versionNumber value="1" />
...
<patient>
<name>
<family>Megan</family>
<given>Brown</given>
</name>
<administrativeGenderCode
code="F"
codeSystem="2.16.840.1.113883.5.1" />
<birthTime value="198110070000" />
<birthplace>
<place>
<addr>
<city>San Jose</city>
<country>United States of America</country>
<postalCode>95102</postalCode>
</addr>
</place>
</birthplace>
</patient>
... |
根据 图 2 中的例子,这个 CDA 文档需要添加病人的地址信息。清单 6 展示了一个 CDA 文档的摘录,其中加入了病人的地址信息。此外,该摘录还包含必要的版本控制信息。
清单 6. 更新后的 HL7 CDA 示例 XML 文档的摘录
...
<id root="2.16.840.1.113883.3.18.1" extension="2-1"/>
<setId root="2.16.840.1.113883.3.18.1" extension="2"/>
<versionNumber value= "2" />
...
<addr>
<streetName>Martine Ave</streetName>
<houseNumber>11</houseNumber>
<houseNumberNumeric>11</houseNumberNumeric>
<city>San Jose</city>
<postalCode>95102</postalCode>
<country>United States of America</country>
</addr>
<patient>
<name>
<family>Megan</family>
<given>Brown</given>
</name>
<administrativeGenderCode
code="F"
codeSystem="2.16.840.1.113883.5.1" />
<birthTime value="198110070000" />
...
</patient>
...
<relatedDocument typeCode="RPLC">
<parentDocument>
<id root="2.16.840.1.113883.3.18.1"
extension="2" />
</parentDocument>
</relatedDocument>
... |
要执行对 CDA 文档的更新,同时又保留原始的 CDA 文档,并增加适当的版本控制信息,可以使用清单 7 演示的 SQL/XML 语句:
清单 7. 执行对 CDA 文档的更新的 SQL/XML 语句
INSERT INTO BUCKET (id, document)
VALUES (11,
XMLQUERY('declare default element namespace "urn:hl7-org:v3";
for $doc in $p
let $newAddress := <addr>
<streetName>Martine Ave</streetName>
<houseNumber>11</houseNumber>
<houseNumberNumeric>11</houseNumberNumeric>
<city>San Jose</city>
<postalCode>95102</postalCode>
<country>United States of America</country>
</addr>
let $IdRoot := $doc/ClinicalDocument/id/_cnnew1@root
let $IdExtension := $doc/ClinicalDocument/id/@extension
let $relationship := <relatedDocument typeCode="RPLC">
<parentDocument>
<id root="{$IdRoot}"
extension="{$IdExtension}" />
</parentDocument>
</relatedDocument>
return transform
copy $c := $doc
modify (do insert $newAddress
after $c/ClinicalDocument/recordTarget/patientRole/id,
do replace
value of $c/ClinicalDocument/versionNumber/@value
with xs:integer($c/ClinicalDocument/versionNumber/@value)+1,
do replace
value of $c/ClinicalDocument/id/@extension
with fn:concat($c/ClinicalDocument/id/@extension, "-1"),
do insert $relationship
after $c/ClinicalDocument/recordTarget)
return $c' PASSING (SELECT document
FROM bucket
WHERE id=1) as "p")
)@ |

 |

|
UBL 订单(版本控制)
Universal Business Language(UBL)(见 参考资料)是由结构化信息标准促进组织(Organization for the Advancement of Structured
Information Standards,OASIS)技术委员会(见
参考资料)开发的,其目的是定义一个免版税的标准电子 XML 商业文档,例如订单和发票库。OASIS 技术委员会将 UBL 定义为 “……被设计为可直接插入到已有的商业、法律、审计和报表管理实践,避免重新输入已有的基于传真和纸张的供应链数据,并为电子商务或中小型企业提供一个入口点。”
此外,2.0 版的 UBL 还包含用于 “Order” 和 “OrderChange” 文档的 XML 模式,后面的示例场景中将用到它们。在这个场景中,一个商业合作伙伴(买方)向另一个商业合作伙伴(卖方)提交一个订单。卖方通过发回一个 “OrderResponse” 文档确认订单。在收到订单响应后不久,买方注意到交货地址有错误。买方现在可以选择几种方式来更正这个错误:
- 提交一个 “OrderChange” 文档(方案 1;如 图 4 所示)
- 取消原先的订单,并提交一个新的订单(方案 2;如 图 5 所示)
- 使用其他的带外(out-of-band)通信(例如,直接打电话给卖方)
清单 8 显示了原始的 Order XML 文档的摘录,其中含有错误的交货地址:
清单 8. 一个 UBL Order XML 文档的摘录,其中含有不正确的交货地址
<Order ...
...
<cbc:UUID>6E09886B-DC6E-439F-82D1-7CCAC7F4E3B1</cbc:UUID>
<cbc:IssueDate>2007-10-15</cbc:IssueDate>
<cac:BuyerCustomerParty>...</cac:BuyerCustomerParty>
<cac:SellerSupplierParty>...</cac:SellerSupplierParty>
...
<cac:Delivery>
<cac:DeliveryAddress>
<cbc:StreetName>Avon Way</cbc:StreetName>
<cbc:BuildingName>Thereabouts</cbc:BuildingName>
<cbc:BuildingNumber>56A</cbc:BuildingNumber>
<cbc:CityName>Bridgetown</cbc:CityName>
<cbc:PostalZone>ZZ99 1ZZ</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>GB</cbc:IdentificationCode>
</cac:Country>
</cac:DeliveryAddress>
<cac:RequestedDeliveryPeriod>
...
</cac:RequestedDeliveryPeriod>
</cac:Delivery>
...
<cac:OrderLine>
<cac:LineItem>...</cac:LineItem>
...
</cac:OrderLine>
...
</Order> |
方案 1. 买方提交一个 OrderChange 文档,以纠正错误
图 4. 更正已有订单的第 1 种方案
买方使用一个 XQuery 表达式(如 清单
10 所示)来根据已有的 Order 文档(如 清单 8 所示)产生一个 OrderChange 文档(如 清单 9 所示)。
清单 9. 一个 UBL OrderChange XML 文档的摘录,其中包含正确的交货地址
<OrderChange ...
...
<cbc:UUID>6E09886B-DC6E-439F-82D1-8BCFC7A4ECCC</cbc:UUID>
<cbc:IssueDate>2007-10-16</cbc:IssueDate>
<cbc:SequenceNumberID>1</cbc:SequenceNumberID>
<cac:BuyerCustomerParty>...</cac:BuyerCustomerParty>
<cac:SellerSupplierParty>...</cac:SellerSupplierParty>
...
<cac:Delivery>
<cac:DeliveryAddress>
<cbc:StreetName>Stratford Way</cbc:StreetName>
<cbc:BuildingNumber>111</cbc:BuildingNumber>
<cbc:CityName>Bridgetown</cbc:CityName>
<cbc:PostalZone>ZZ99 1ZZ</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>GB</cbc:IdentificationCode>
</cac:Country>
</cac:DeliveryAddress>
<cac:RequestedDeliveryPeriod>
...
</cac:RequestedDeliveryPeriod>
</cac:Delivery>
...
<cac:OrderLine>
<cac:LineItem>...</cac:LineItem>
...
</cac:OrderLine>
...
</OrderChange> |
清单 10. 用于根据 UBL Order XML 文档(清单 8)产生 UBL OrderChange XML 文档(清单 9)的 XQuery 表达式
XQUERY
declare default element namespace
"urn:oasis:names:specification:ubl:schema:xsd:Order-2";
declare namespace cac =
"urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2";
declare namespace cbc =
"urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2";
for $doc in db2-fn:sqlquery('select data from ubladmin.ubltable where id=100')
let $SequenceNumber := <cbc:SequenceNumberID>1</cbc:SequenceNumberID>
let $newAddress := <cac:DeliveryAddress>
<cbc:StreetName>Stratford Way</cbc:StreetName>
<cbc:BuildingNumber>111</cbc:BuildingNumber>
<cbc:CityName>Bridgetown</cbc:CityName>
<cbc:PostalZone>ZZ99 1ZZ</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>GB</cbc:IdentificationCode>
</cac:Country>
</cac:DeliveryAddress>
return transform
copy $c := $doc
modify (do rename $c/Order
as "OrderChange",
do replace
value of $c/Order/cbc:UUID
with "6E09886B-DC6E-439F-82D1-8BCFC7A4ECCC",
do replace
value of $c/Order/cbc:IssueDate
with "2007-10-16",
do insert $SequenceNumber
after $c/Order/cbc:IssueDate,
do replace $c/Order/cac:Delivery/cac:DeliveryAddress
with $newAddress)
return $c |
然后,买方将 OrderChange 文档提交给卖方。为了容纳 Order 文档与 OrderChange 文档之间的差异,XQuery 表达式必须:
- 将
<Order> 元素重命名为 “OrderChange”
- 用新的值替换 UUID 和 IssueDate 元素的值
- 插入一个新的 SequenceNumber
- 用新构造的
<cac:DeliveryAddress> 元素替换已有的元素
也可以不完全替换已有的
<cac:DeliveryAddress> 元素,而是只替换不正确的子元素,如清单 11 所示:
清单 11. 根据 UBL Order XML 文档(清单 8)产生新的 UBL Order XML 文档(清单 12)的 XQuery 表达式
XQUERY
declare default element namespace
"urn:oasis:names:specification:ubl:schema:xsd:Order-2";
declare namespace cac =
"urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2";
declare namespace cbc =
"urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2";
for $doc in db2-fn:sqlquery('select data from ubladmin.ubltable where id=100')
return transform
copy $c := $doc
modify (do replace
value of $c/Order/cbc:UUID
with "6E09886B-DC6E-439F-82D1-8BCFC7A4ECCC",
do replace
value of $c/Order/cbc:IssueDate
with "2007-10-16",
do replace
value of $c/Order/cac:Delivery/cac:DeliveryAddress/cbc:StreetName
with "Stratford Way",
do replace value of
$c/Order/cac:Delivery/cac:DeliveryAddress/cbc:BuildingNumber
with "111",
do delete
$c/Order/cac:Delivery/cac:DeliveryAddress/cbc:BuildingName)
return $c |
方案 2。买方取消已有的订单,并提交一个新的 Order 文档,以更正错误。
图 5. 更正已有订单的第 2 种方案
买方可以使用一个类似于 清单 11 所示的 XQuery 表达式来根据已有的 Order 文档(清单 8)产生一个新的 Order 文档(清单 12),并将这个新的 Order 文档提交给卖方。
清单 12. 新的 UBL Order XML 文档的摘录,其中包含正确的地址
<Order ...
...
<cbc:UUID>6E09886B-DC6E-439F-82D1-8BCFC7A4ECCC</cbc:UUID>
<cbc:IssueDate>2007-10-16</cbc:IssueDate>
<cac:BuyerCustomerParty>...</cac:BuyerCustomerParty>
<cac:SellerSupplierParty>...</cac:SellerSupplierParty>
...
<cac:Delivery>
<cac:DeliveryAddress>
<cbc:StreetName>Stratford Way</cbc:StreetName>
<cbc:BuildingNumber>111</cbc:BuildingNumber>
<cbc:CityName>Bridgetown</cbc:CityName>
<cbc:PostalZone>ZZ99 1ZZ</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>GB</cbc:IdentificationCode>
</cac:Country>
</cac:DeliveryAddress>
<cac:RequestedDeliveryPeriod>
...
</cac:RequestedDeliveryPeriod>
</cac:Delivery>
...
<cac:OrderLine>
<cac:LineItem>...</cac:LineItem>
...
</cac:OrderLine>
...
</Order> |
为了创建新的 Order 文档,XQuery 表达式必须用新的值替换 UUID 和 IssueDate 元素的值,并用正确的值替换
<cbc:StreetName> 和
<cbc:BuildingNumber> 元素现有的值,然后删除
<cbc:BuildingName> 元素。
FpML 衍生产品(约务更替请求响应)
金融产品标记语言(Financial products Markup Language,FpML)是由国际互换和衍生产品协会(
International Swaps and Derivatives Association,ISDA)定义的一套 XML 标记法,用于描述私下议定的衍生产品(契约)。在创建 FpML 的过程中,ISDA 代表进行场外交易(Over the Counter,OTC)的投资银行(要了解关于 ISDA、FpML 的更多信息,请参阅
参考资料)。
XML 非常适合 FpML,因为随时都有新的衍生产品被创造出来,所以需要一套灵活的标记法。FpML 难以用诸如关系表之类的其他标记法来表示,因为如今的 FpML 已经有超过 600 种 XML 类型,超过 1730 种 XML 元素,以及超过 21 个 XML 模式文件(XSD)。
本文中的 FpML XQuery 更新例子(参见
图 6)演示了如何为一个约务更替请求产生一个响应(参见 参考资料)。约务更替是指将契约中已有的一方替换为新的一方的一个协定。
图 6. FpML 约务更替
代码片段
清单 13 显示了一个约务更替请求:
清单 13. 约务更替请求的摘录
<FpML version="4-2"
xmlns=http://www.fpml.org/2005/FpML-4-2
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.fpml.org/2005/FpML-4-2
../../fpml-main-4-2.xsd
http://www.w3.org/2000/09/xmldsig#
xmldsig-core-schema.xsd"
xsi:type="NovationConsentRequest">
...
<novation>
<oldTransaction>
<partyTradeIdentifier>
<partyReference href="abcBank"/>
<tradeId tradeIdScheme=
"http://www.abcbank.com/tradeId/OTC">
TradeABC0001
</tradeId>
</partyTradeIdentifier>
</oldTransaction>
<newTransactionReference>
<partyTradeIdentifier>
<partyReference href="xyzBank"/>
<tradeId tradeIdScheme=
"http://www.xyzbank.com/tradeId/OTC">
TradeXYZ0001
</tradeId>
</partyTradeIdentifier>
</newTransactionReference> |
清单 14 显示了期望的约务更替响应。
清单 14. 约务更替响应的摘录
<FpML version="4-2"
xmlns=http://www.fpml.org/2005/FpML-4-2
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.fpml.org/2005/FpML-4-2
../../fpml-main-4-2.xsd
http://www.w3.org/2000/09/xmldsig#
xmldsig-core-schema.xsd"
xsi:type="NovationConsentGranted">
...
<novation>
<oldTransactionReference>
<partyTradeIdentifier>
<partyReference href="abcBank"/>
<tradeId tradeIdScheme=
"http://www.abcbank.com/tradeId/OTC">
TradeABC0001
</tradeId>
</partyTradeIdentifier>
</oldTransactionReference>
<newTransactionReference>
<partyTradeIdentifier>
<partyReference href="xyzBank"/>
<tradeId tradeIdScheme=
"http://www.xyzbank.com/tradeId/OTC">
TradeXYZ0001
</tradeId>
</partyTradeIdentifier>
</newTransactionReference> |
清单 15 展示了如何使用 XQuery 更新产生约务更替响应或确认。
清单 15. 产生 FpML 约务更替确认的 SQL/XML 语句
INSERT INTO BUCKET (id, document)
VALUES (33,
XMLQUERY('declare default element namespace "http://www.fpml.org/2005/FpML-4-2";
declare namespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
for $doc in $f
let $reference := $doc/FpML/novation/oldTransaction/tradeHeader
/partyTradeIdentifier[last()]
let $oldReference := <oldTransactionReference>
{$reference}
</oldTransactionReference>
return transform
copy $c := $doc
modify (do replace
value of $c/FpML/@xsi:type
with "NovationConsentGranted",
do insert $oldReference
before $c/FpML/novation/newTransactionReference,
do delete $c/FpML/novation/oldTransaction)
return $c' PASSING (SELECT document
FROM bucket
WHERE id=3) as "f")
)@ |
Web 2.0 APP — 用于 Atom Store 的 API(在内存中更新)
Atom 描述两个相关的标准(要了解更多信息,请参阅
参考资料):
- Atom Syndication Format 是一套 XML 标记法,用于描述 Web 提要的布局。一个提要有很多条目。例如,一组属于特定类别(例如中国体育)的最新新闻可以表示为一个 atom 提要。每条新闻将由一个 Atom 条目表示。
-
Atom Publishing Protocol(APP)是用于创建和更新 Atom 格式的 Web 资源的一个 HTTP 协议。APP 的目的在于鼓励资源采用 Atom 表示。
以 Atom 标记法存储的 XML 的数据集合称作 Atom
Store。
图 7. Atom 场景
XML 非常适合于 Atom,因为有很多支持交换和存储 Atom 提要的不同类型的工具和技术,包括人类用户界面软件(参见 图 7)。
本文中的 Atom XQuery 更新例子演示如何修改一个 Atom 提要条目。清单 16 显示了一个提要条目:
清单 16. 一个 Atom 条目
<entry xmlns="http://www.w3.org/2005/Atom">
<author>
<name>Lonely John</name>
</author>
<title>Scary Nights</title>
<content type="xhtml" xml:lang="en-US">
<div xmlns="http://www.w3.org/1999/xhtml">
It was a dark and stormy night
</div>
</content>
<published>
2006-07-13T10:59:26-07:00
</published>
</entry> |
清单 17 显示了这个条目进行了修改并添加了更多链接之后的样子:
清单 17. 更新后的 Atom 条目
<entry xmlns="http://www.w3.org/2005/Atom">
<author>
<name>John the brave</name>
<email>johnb@ibm.com</email>
</author>
<id xmlns="http://www.w3.org/2005/Atom">b8b2332285095249</id>
<summary xmlns="http://www.w3.org/2005/Atom" type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<a href="http://atomfeeds.com?col=97">
<img src="http://atomfeeds.com?col=97"
alt="Media of type application"/>
</a>
</div>
</summary>
<created xmlns="http://www.w3.org/2005/Atom"
by="johnb@ibm.com">2007-09-26T21:15:10.541636Z
</created>
<updated xmlns="http://www.w3.org/2005/Atom"
by="johnb@ibm.com">2007-09-26T21:15:10.541636Z
</updated>
<link xmlns="http://www.w3.org/2005/Atom" rel="self"
href="http://atomfeeds.com?col=97"/>
<link xmlns="http://www.w3.org/2005/Atom" rel="edit"
href="http://atomfeeds.com?col=97"/>
<link xmlns="http://www.w3.org/2005/Atom" rel="edit-media"
href="http://atomfeeds.com?col=97&media"/>
<title>Media of type application</title>
<content xmlns="http://www.w3.org/2005/Atom"
type="application/x-www-form-urlencoded"
src="http://atomfeeds.com?col=97"/>
</entry> |
清单 18 显示如何使用 XQuery 更新实现 Atom Publishing Protocol 的某些方面,并产生修改后的 Atom 提要条目:
清单 18. 根据原始条目产生修改后的 Atom 提要条目的 XQuery 更新
XQUERY declare default element namespace 'http://www.w3.org/2005/Atom';
for $doc in db2-fn:sqlquery('select document from bucket where id=2')
let $newTitle := "Media of type application"
let $newAuthor := <author>
<name>John the brave</name>
<email>johnb@ibm.com</email>
</author>
let $newId := <id>b8b2332285095249</id>
let $summary := <summary type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<a href="http://atomfeeds.com?col=97">
<img src="http://atomfeeds.com?col=97"
alt="Media of type application"/></a>
</div>
</summary>
let $newContent := <content type="application/x-www-form-urlencoded"
src="http://atomfeeds.com?col=97"/>
let $created := <created by="johnb@ibm.com">2007-09-26T21:15:10.541636Z</created>
let $updated := <updated by="johnb@ibm.com">2007-09-26T21:15:10.541636Z</updated>
let $linkSelf := <link rel="self" href="http://atomfeeds.com?col=97"/>
let $linkEdit := <link rel="edit" href="http://atomfeeds.com?col=97"/>
let $linkEditMedia := <link rel="edit-media" href="http://atomfeeds.com?col=97&media"/>
return transform copy $c := $doc
modify (do delete $c/entry/published,
do replace value of $c/entry/title with $newTitle,
do replace $c/entry/author with $newAuthor,
do replace $c/entry/content with $newContent,
do insert $newId after $c/entry/author,
do insert $summary after $c/entry/author,
do insert $created after $c/entry/author,
do insert $updated after $c/entry/author,
do insert $linkSelf after $c/entry/author,
do insert $linkEdit after $c/entry/author,
do insert $linkEditMedia after $c/entry/author)
return $c@ |

 |

|
一些指导原则
当把 XML 存储在数据库中并处理修改请求时,一个常见的策略是原样保留原先存储的 XML,并创建一个修改后的新版本的 XML,再通过时间戳标记、版本控制(或结合两者)等手段标明做出更改的时间以及更改何时生效。有些行业(例如卫生保健)的消息格式解释如何通过显式的版本控制处理修改后的数据。
包含某种版本控制或时间戳标记的设计方法可以较真实地反映外部世界发生的事情,更易于将计算机系统中的处理与现实世界中的惯例和实践相关联。版本控制和时间戳标记使得遵从性更易于处理。
结束语
本文在 4 个行业(卫生保健、商业、金融衍生业和信息技术)的上下文中展示如何使用 XQuery 更新来修改存储在内存或 DB2 pureXML 数据库中的 XML。
在现实世界中,特别是在涉及到金钱的时候,通常很少直接修改信息,好的做法是维护一个更改历史。同时存储 XML 消息和从已有 XML 产生的新版本的消息,有助于支持治理和遵从性计划。
在本文中,您学习了如何根据上述指导原则,通过 XQuery 更新功能为存储中的 XML 创建新的版本,或者,在不必维护审计或者有另一个系统在执行审计的情况下,在原处替换存储的 XML。本文还演示了如何使用 XQuery 更新来根据 XML 请求消息生成 XML 响应消息,或者使用视图隐藏信息。
参考资料 学习
获得产品和技术
-
DB2 Express-C:下载免费版的 DB2,它具有与其他 Data Servers 相同的核心功能,例如 pureXML 技术。DB2 Express-C 可以免费用于开发、部署和发布。
- 用可直接从 developerWorks 下载的
IBM 试用软件 构建您的下一个开发项目。
讨论
作者简介  | 
|  | Susan Malaika 是 IBM Information Management Group(属于 IBM Software Group)的一名高级技术人员。她的专长包括 XML、Web 和数据库。她曾在 Global Grid Forum 开发过支持网格环境数据的标准。她与人合作出版了关于 Web 的专著,发表了关于事务处理和 XML 的文章。她是 IBM Academy of Technology 的成员。 |
 | 
|  | Jan-Eike Michels 是 IBM Information Management
Group(隶属于 IBM Software Group)的一名软件工程师。他在
ANSI/INCITS/H2 and ISO/JTC1/SC32/WG3 委员会代表 IBM,负责标准化 SQL 和 SQL/XML。他还与 DB2 XML 开发小组以及正在使用 XML 的客户和合作伙伴合作,帮助他们实现 XML 解决方案。他拥有德国伊尔梅瑙工业大学计算机科学硕士学位。 |
 | 
|  | Christian Pichler 是来自奥地利维也纳技术大学的带薪实习生,正在撰写计算机工程和计算机科学双硕士学位的论文,论文主题是医疗保健。在 IBM 的实习阶段,Christian 现在从事将 XML 存储到 DB2,以及通过 Web 服务、提要和 XForm 访问 XML 方面的工作。他专长于医疗保健方面的 XML 标准。 |
对本文的评价
|