XRX/元数据购物者
您希望允许非程序员(业务分析师、项目经理、业务部门、主题专家等)能够从元数据注册表中创建精确的数据元素列表。此工具具有一个搜索功能,允许这些用户查找数据元素,然后将它们添加到可以保存以供将来使用的列表中。此列表(称为愿望清单)然后可以用来生成子模式,这些子模式被导入 XML 交换文档中。
元数据购物者是允许非程序员创建精确的数据交换规范的关键工具之一。任何接受过几小时培训的人现在都可以创建精确的数据元素列表,这些元素在语义上与其他数据交换一致。一般来说,购物车帮助用户找到数据交换树上的“叶子”。这些元素的确切顺序、哪些元素是必需的、嵌套结构以及交换中元素的数量通常不被认为是元数据购物过程的一部分。这些被认为是数据交换的“约束”,而不是数据交换的语义。语义由愿望清单驱动,约束通常包含在交换的 XML 模式中。
这种将数据交换的语义与交换的约束分离的模式被称为关注点分离,是允许非程序员更多参与创建数据交换流程的主要驱动力之一。
我们将创建一个 XForms 应用程序,它有两个“提交”元素。一个用于获取搜索结果,另一个用于保存愿望清单。当用户看到他们想要保留的搜索结果时,它将被添加到愿望清单中。在会话结束时,用户通常会将他们的愿望清单保存在愿望清单注册表中。
此程序创建的愿望清单旨在用于子模式生成器,该生成器将在本书后面讨论。
这是一个在您开始搜索数据元素之前购物车样例屏幕截图
这是在搜索字段中输入“姓氏”等搜索词并获得单个命中后的结果。获得此命中后,您可以单击添加按钮并观察结果添加到右侧的愿望清单中。
这是一个示例屏幕截图,显示了在将几个元数据元素添加到购物车之后的样子。
元数据购物者依赖于数据元素搜索服务,该服务将返回与查询匹配的数据元素列表。
例如,如果数据元素查询的 URL 为以下内容
BASENAME/search/search.xq?q=birth
结果集的格式如下
<results>
<DataElement>
<DataElementName>PersonBirthDate</DataElementName>
<NamespaceURI>http://www.example.com/registry<NamespaceURI>
<DataElementDefinitionText>The date a person was born.</DataElementDefinitionText>
</DataElement>
<DataElement>
<DataElementName>PersonGivenName</DataElementName>
<NamespaceURI>http://www.example.com/registry<NamespaceURI>
<DataElementDefinitionText>The name given to a person at birth. Also referred to as a first name in western cultures.</DataElementDefinitionText>
</DataElement>
</results>
在将搜索提交发送到服务器后,搜索结果会返回并自动填充表单中的搜索结果实例。这是在不重新加载表单的情况下完成的。
以下 XQuery 动态生成一个 XForms 应用程序。我们使用 XQuery 生成表单,因为我们经常希望使用默认愿望清单对其进行参数化。
xquery version "1.0";
declare option exist:serialize "method=xml media-type=text/xml indent=yes";
let $title := 'Basic Metadata Shopper Version 1'
return
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:ev="http://www.w3.org/2001/xml-events">
<head>
<title>{$title}</title>
<link rel="stylesheet" type="text/css" href="shopping-cart.css"/>
<xf:model>
<!-- here is where you store the search query before you hit the "search button". -->
<xf:instance xmlns="" id="search-criteria">
<data>
<q/>
</data>
</xf:instance>
<xf:instance xmlns="" id="shopping-cart">
<data>
<FileName>test.xml</FileName>
<!-- Thing from the OWN namespace -->
<DataElement>
<DataElementName>Thing</DataElementName>
<NamespaceURI>http://www.w3.org/2002/07/owl</NamespaceURI>
<definition>The root of all data elements.</definition>
</DataElement>
</data>
</xf:instance>
<xf:instance xmlns="" id="search-response">
<data/>
</xf:instance>
<xf:instance xmlns="" id="save-wantlist-response">
<data/>
</xf:instance>
<xf:submission id="search" ref="instance('search-criteria')" method="get" action="search-elements.xq" replace="instance" instance="search-response" separator="&">
<xf:toggle case="case-busy" ev:event="xforms-submit"/>
<xf:toggle case="case-submit-error" ev:event="xforms-submit-error"/>
<xf:toggle case="case-done" ev:event="xforms-submit-done"/>
</xf:submission>
<xf:submission id="save-wantlist" ref="instance('shopping-cart')" method="post" action="../edit/save-new.xq" replace="instance" instance="save-wantlist-response" separator="&">
<xf:toggle case="save-wantlist-case-busy" ev:event="xforms-submit"/>
<xf:toggle case="save-wantlist-case-submit-error" ev:event="xforms-submit-error"/>
<xf:toggle case="save-wantlist-case-done" ev:event="xforms-submit-done"/>
</xf:submission>
<!-- just for testing if you don't have an instance inspector in the browser like XForms buddy -->
<xf:submission id="echo-search-criteria" ref="instance('search-criteria')" method="post" action="../xqueries/echo-test.xq" replace="all"/>
<xf:submission id="echo-wantlist" ref="instance('shopping-cart')" method="post" action="../xqueries/echo-test.xq" replace="all"/>
</xf:model>
</head>
<body>
<a class="breadcrumb" href="../index.xhtml">Metadata Registry Home</a> >
<a class="breadcrumb" href="index.xhtml">Shopping Cart Home</a>
<div class="search">
<h1>Metadata Shopper</h1>
<xf:input ref="instance('search-criteria')/string" incremental="true">
<xf:label>Search:</xf:label>
</xf:input>
<xf:submit submission="search">
<xf:label>Search</xf:label>
</xf:submit>
<xf:switch>
<xf:case id="ready">
<!-- <xf:submit submission="echo-search-criteria">
<xf:label>Echo Search Criteria</xf:label>
</xf:submit> -->
</xf:case>
<xf:case id="case-busy">
<p>Waiting for response...</p>
</xf:case>
<xf:case id="case-submit-error">
<p>The server has returned a submit error event.</p>
</xf:case>
<xf:case id="case-done">
<div class="search-results">
<h3>Search Results:</h3>
<xf:repeat id="search-results-repeat" nodeset="instance('search-response')/DataElement">
<div class="result">
<xf:trigger>
<xf:label>Add</xf:label>
<xf:action ev:event="DOMActivate">
<xf:insert nodeset="instance('shopping-cart')/DataElement" at="last()" position="after"/>
<!-- the nth one selected -->
<xf:setvalue ref="instance('debug')/search-index" value="index('search-results-repeat')"/>
<xf:setvalue ref="instance('debug')/item-to-add" value="instance('search-response')/DataElement[index('search-results-repeat')=position()]/DataElementName"/>
<!-- set the last element in the cart to the selected item -->
<xf:setvalue ref="instance('shopping-cart')/DataElement[last()]/DataElementName" value="instance('search-response')/DataElement[index('search-results-repeat')=position()]/DataElementName"/>
</xf:action>
</xf:trigger>
<div class="result-text">
<b>
<xf:output ref="DataElementName"/>
</b>
<i>
<xf:output ref="DataElementDefinitionText/text()"/>
</i>
</div>
</div>
</xf:repeat>
</div>
</xf:case>
</xf:switch>
<xf:switch>
<xf:case id="ready"/>
<xf:case id="save-wantlist-case-busy">
<p>Waiting for response...</p>
</xf:case>
<xf:case id="save-wantlist-case-submit-error">
<p>The server has returned a submit error event.</p>
</xf:case>
<xf:case id="save-wantlist-case-done">
<div class="search-results">
<xf:repeat id="search-results-repeat" nodeset="instance('save-wantlist-response')/results">
<xf:output ref="Message/text()"/>
</xf:repeat>
</div>
</xf:case>
</xf:switch>
</div>
<div class="shopping-cart-sidebar">
<img src="shopping-cart.jpg" height="50"/>
<h3>Shopping Cart Contents:</h3>
<ul>
<xf:repeat id="shopping-cart-repeat" nodeset="instance('shopping-cart')/DataElement">
<li>
<xf:output value="concat(prefix,':', DataElementName)" class="url"/>
<!-- TODO figure out how to bind an output to a URL<xf:output
value="concat(
'http://dlficsb501:8080/exist/rest/db/mdr/data-elements/views/view-data-element.xq?id=',
DataElementName,
prefix,':', DataElementName
)"
class="url" /> -->
</li>
</xf:repeat>
<br/>
<xf:input ref="instance('shopping-cart')/FileName">
<xf:label><b>Wantlist name:</b></xf:label>
</xf:input>
<xf:submit submission="save-wantlist">
<xf:label>Save Wantlist</xf:label>
</xf:submit>
<!--
<xf:submit submission="echo-wantlist">
<xf:label>Echo Wantlist</xf:label>
</xf:submit>
-->
</ul>
</div>
</body>
</html>
您可能还想将多个元素复制到购物车中,例如书名和书的价格。为此,您可以使用 XForms 插入的新“origin”属性,不仅复制单个元素,而且将整个复杂节点复制到购物车中。