如何在另一个元素的相关规则中使用日期格式可以为空的输入字段?
How to use input fields with date format that can be null in a relevant rule of another element?
我有一个简单的表单,其中包含一些日期字段和单选按钮。其中一个元素有一个相关规则,它依赖于前面两个问题,一个是单选按钮,另一个是日期字段。
我这里创建了一个简单的例子,可以直接在Orbeon中运行:
<xh:html xmlns:xh="http://www.w3.org/1999/xhtml"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:exf="http://www.exforms.org/exf/1-0"
xmlns:fb="http://orbeon.org/oxf/xml/form-builder"
xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
xmlns:saxon="http://saxon.sf.net/"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sql="http://orbeon.org/oxf/xml/sql"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
xmlns:xxi="http://orbeon.org/oxf/xml/xinclude">
<xh:head>
<xh:meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
<xh:title>DateTest</xh:title>
<xf:model id="fr-form-model" xxf:expose-xpath-types="true">
<xf:instance xxf:readonly="true" id="fr-form-metadata" xxf:exclude-result-prefixes="#all">
<metadata>
<application-name>WebForms</application-name>
<form-name>DateTest_v1</form-name>
<title xml:lang="en">DateTest</title>
<description xml:lang="en">Version: 1. Modification date: 2015-05-27 14:43:59. Publication date: 2015-05-27 14:43:59.</description>
<singleton>false</singleton>
</metadata>
</xf:instance>
<xf:instance id="fr-form-instance">
<form>
<Category>
<Question1/>
<Question2/>
<Question3/>
<Question4/>
</Category>
</form>
</xf:instance>
<xf:bind id="fr-form-binds" ref="instance('fr-form-instance')">
<xf:bind id="Category-bind" name="Category" ref="/form/Category">
<xf:bind id="Question1-bind" name="Question1" ref="Question1" required="true()"/>
<xf:bind id="Question2-bind" name="Question2" readonly="false" ref="Question2"
relevant="(( $Question1='Answer' ) )"
required="true()"
type="xf:date"/>
<xf:bind id="Question3-bind" name="Question3" readonly="false" ref="Question3"
relevant="(( $Question1='Answer' and string-length($Question1/text()) > 0 ) )"
required="true()"
type="xf:date"/>
<xf:bind id="Question4-bind" name="Question4" readonly="false" ref="Question4"
relevant="(( xs:date($Question2) > xs:date('2015-05-20')) or ( $Question1='Answer2' ) )"
required="true()"/>
</xf:bind>
</xf:bind>
<xf:instance id="fr-form-attachments">
<attachments>
<css filename="" mediatype="text/css" size=""/>
<pdf filename="" mediatype="application/pdf" size=""/>
</attachments>
</xf:instance>
<xf:instance id="fr-form-resources" xxf:readonly="false">
<resources>
<resource xml:lang="en">
<Category>
<label>Category</label>
<hint/>
<alert/>
<Question1>
<label>Question1</label>
<hint/>
<alert/>
<item>
<label>Answer</label>
<hint/>
<value>Answer</value>
</item>
<item>
<label>Answer2</label>
<hint/>
<value>Answer2</value>
</item>
</Question1>
<Question2>
<label>Question2</label>
<hint/>
<alert/>
</Question2>
<Question3>
<label>Question3</label>
<hint/>
<alert/>
</Question3>
<Question4>
<label>Question4</label>
<hint/>
<alert/>
<item>
<label>Answer</label>
<hint/>
<value>Answer</value>
</item>
<item>
<label>Answer2</label>
<hint/>
<value>Answer2</value>
</item>
</Question4>
</Category>
</resource>
</resources>
</xf:instance>
<xf:instance id="fr-service-response-instance" xxf:exclude-result-prefixes="#all">
<response/>
</xf:instance>
</xf:model>
</xh:head>
<xh:body>
<fr:view>
<fr:body xmlns:xbl="http://www.w3.org/ns/xbl"
xmlns:oxf="http://www.orbeon.com/oxf/processors"
xmlns:p="http://www.orbeon.com/oxf/pipeline"
xmlns:dataModel="java:org.orbeon.oxf.fb.DataModel">
<fr:section bind="Category-bind" class="webforms-element webforms-category"
id="Category-control">
<xf:label mediatype="text/html" ref="$form-resources/Category/label"/>
<xf:hint ref="$form-resources/Category/hint"/>
<xf:alert ref="$form-resources/Category/alert"/>
<xh:tr>
<xh:td>
<xf:select1 appearance="full" bind="Question1-bind"
class="webforms-element webforms-question"
id="Question1-control">
<xf:label mediatype="text/html" ref="$form-resources/Category/Question1/label"/>
<xf:hint ref="$form-resources/Category/Question1/hint"/>
<xf:alert ref="$form-resources/Category/Question1/alert"/>
<xf:itemset class="webforms-element webforms-answer"
ref="$form-resources/Category/Question1/item">
<xf:label ref="label"/>
<xf:value ref="value"/>
<xf:hint ref="hint"/>
</xf:itemset>
</xf:select1>
</xh:td>
</xh:tr>
<xh:tr>
<xh:td>
<xf:input bind="Question2-bind" class="webforms-element webforms-question"
id="Question2-control">
<xf:label mediatype="text/html" ref="$form-resources/Category/Question2/label"/>
<xf:hint ref="$form-resources/Category/Question2/hint"/>
<xf:alert ref="$form-resources/Category/Question2/alert"/>
</xf:input>
</xh:td>
</xh:tr>
<xh:tr>
<xh:td>
<xf:input bind="Question3-bind" class="webforms-element webforms-question"
id="Question3-control">
<xf:label mediatype="text/html" ref="$form-resources/Category/Question3/label"/>
<xf:hint ref="$form-resources/Category/Question3/hint"/>
<xf:alert ref="$form-resources/Category/Question3/alert"/>
</xf:input>
</xh:td>
</xh:tr>
<xh:tr>
<xh:td>
<xf:select1 appearance="full" bind="Question4-bind"
class="webforms-element webforms-question"
id="Question4-control">
<xf:label mediatype="text/html" ref="$form-resources/Category/Question4/label"/>
<xf:hint ref="$form-resources/Category/Question4/hint"/>
<xf:alert ref="$form-resources/Category/Question4/alert"/>
<xf:itemset class="webforms-element webforms-answer"
ref="$form-resources/Category/Question4/item">
<xf:label ref="label"/>
<xf:value ref="value"/>
<xf:hint ref="hint"/>
</xf:itemset>
</xf:select1>
</xh:td>
</xh:tr>
</fr:section>
</fr:body>
</fr:view>
</xh:body>
</xh:html>
有趣的是问题4,有相关规则(( xs:date($Question2) > xs:date('2015-05-20')) or ($Question1='Answer2'))
。
如果我先写xs:date($Question2) > xs:date('2015-05-20')
的部分,然后在OR运算符中写$Question1='Answer2'
的部分,当Question1
选择了Answer2
时,问题4不是显示。这意味着 OR 运算符的右侧部分将被忽略。但是,如果我将相关规则更改为 (( $Question1='Answer2') or (xs:date($Question2) > xs:date('2015-05-20')))
,则行为在两种情况下都完美无缺:如果 Question1 = answer 或日期字段具有正确的值,则会显示 Question4。
似乎将日期放在首位给我带来了一些问题。可能是因为如果Question3因流程不填,date为空值,相关规则运行不正确。
我也尝试了一些替代方法,例如检查添加 string-length(format-date($Question3), '[MNn,*-3]/[D01]/[Y]')) > 0
或 if(not(normalize-space($Question2) = '')) then ( xs:date($Question2) > xs:date('2015-05-20')) else false
的字段的长度,如果它是空的,则忽略日期字段运算符的处理范围。但一点运气都没有。
对于其他不同类型的日期,相关规则正常工作,因此我认为问题出在我的日期字段上。
如果这是预期的行为,问题是:如何以正确的方式使用日期字段以使相关规则正常工作?
首先,当 foo
是日期时,您不需要使用 xs:date($foo)
,type annotations enabled 现在是您在 Form Builder 中创建的表单的默认值。但这对你的情况没有多大帮助,因为当评估 $Question2 > xs:date('2015-05-20')
时,如果 $Question2
不是日期,整个表达式将失败,就像你写了 xs:date($Question2)
.所以在你的情况下,你需要:
- 首先在复选框上进行测试(您已经知道这行得通)。
- 写成
$Question2 castable as xs:date and $Question2 > xs:date('2015-05-20')
,这样当 $Question2
不是日期时,这部分表达式不会失败,但 return 为 false。
我们已经看到这个问题的几个变体,我们目前认为我们可以通过将 XForms 引擎更改为 return 一个空序列来解决这个问题,当 $Question2
的输入值时被访问并且 $Question2
不是日期(或它应该是的任何类型)。这将等同于 () > xs:date('2015-05-20')
,其中 return 是错误的,并且适用于您的情况。如果您有兴趣,RFE 2251 中对此有更详细的介绍。但同样,现在,您将不得不求助于上述两种技术之一。
我有一个简单的表单,其中包含一些日期字段和单选按钮。其中一个元素有一个相关规则,它依赖于前面两个问题,一个是单选按钮,另一个是日期字段。 我这里创建了一个简单的例子,可以直接在Orbeon中运行:
<xh:html xmlns:xh="http://www.w3.org/1999/xhtml"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:exf="http://www.exforms.org/exf/1-0"
xmlns:fb="http://orbeon.org/oxf/xml/form-builder"
xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
xmlns:saxon="http://saxon.sf.net/"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sql="http://orbeon.org/oxf/xml/sql"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
xmlns:xxi="http://orbeon.org/oxf/xml/xinclude">
<xh:head>
<xh:meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
<xh:title>DateTest</xh:title>
<xf:model id="fr-form-model" xxf:expose-xpath-types="true">
<xf:instance xxf:readonly="true" id="fr-form-metadata" xxf:exclude-result-prefixes="#all">
<metadata>
<application-name>WebForms</application-name>
<form-name>DateTest_v1</form-name>
<title xml:lang="en">DateTest</title>
<description xml:lang="en">Version: 1. Modification date: 2015-05-27 14:43:59. Publication date: 2015-05-27 14:43:59.</description>
<singleton>false</singleton>
</metadata>
</xf:instance>
<xf:instance id="fr-form-instance">
<form>
<Category>
<Question1/>
<Question2/>
<Question3/>
<Question4/>
</Category>
</form>
</xf:instance>
<xf:bind id="fr-form-binds" ref="instance('fr-form-instance')">
<xf:bind id="Category-bind" name="Category" ref="/form/Category">
<xf:bind id="Question1-bind" name="Question1" ref="Question1" required="true()"/>
<xf:bind id="Question2-bind" name="Question2" readonly="false" ref="Question2"
relevant="(( $Question1='Answer' ) )"
required="true()"
type="xf:date"/>
<xf:bind id="Question3-bind" name="Question3" readonly="false" ref="Question3"
relevant="(( $Question1='Answer' and string-length($Question1/text()) > 0 ) )"
required="true()"
type="xf:date"/>
<xf:bind id="Question4-bind" name="Question4" readonly="false" ref="Question4"
relevant="(( xs:date($Question2) > xs:date('2015-05-20')) or ( $Question1='Answer2' ) )"
required="true()"/>
</xf:bind>
</xf:bind>
<xf:instance id="fr-form-attachments">
<attachments>
<css filename="" mediatype="text/css" size=""/>
<pdf filename="" mediatype="application/pdf" size=""/>
</attachments>
</xf:instance>
<xf:instance id="fr-form-resources" xxf:readonly="false">
<resources>
<resource xml:lang="en">
<Category>
<label>Category</label>
<hint/>
<alert/>
<Question1>
<label>Question1</label>
<hint/>
<alert/>
<item>
<label>Answer</label>
<hint/>
<value>Answer</value>
</item>
<item>
<label>Answer2</label>
<hint/>
<value>Answer2</value>
</item>
</Question1>
<Question2>
<label>Question2</label>
<hint/>
<alert/>
</Question2>
<Question3>
<label>Question3</label>
<hint/>
<alert/>
</Question3>
<Question4>
<label>Question4</label>
<hint/>
<alert/>
<item>
<label>Answer</label>
<hint/>
<value>Answer</value>
</item>
<item>
<label>Answer2</label>
<hint/>
<value>Answer2</value>
</item>
</Question4>
</Category>
</resource>
</resources>
</xf:instance>
<xf:instance id="fr-service-response-instance" xxf:exclude-result-prefixes="#all">
<response/>
</xf:instance>
</xf:model>
</xh:head>
<xh:body>
<fr:view>
<fr:body xmlns:xbl="http://www.w3.org/ns/xbl"
xmlns:oxf="http://www.orbeon.com/oxf/processors"
xmlns:p="http://www.orbeon.com/oxf/pipeline"
xmlns:dataModel="java:org.orbeon.oxf.fb.DataModel">
<fr:section bind="Category-bind" class="webforms-element webforms-category"
id="Category-control">
<xf:label mediatype="text/html" ref="$form-resources/Category/label"/>
<xf:hint ref="$form-resources/Category/hint"/>
<xf:alert ref="$form-resources/Category/alert"/>
<xh:tr>
<xh:td>
<xf:select1 appearance="full" bind="Question1-bind"
class="webforms-element webforms-question"
id="Question1-control">
<xf:label mediatype="text/html" ref="$form-resources/Category/Question1/label"/>
<xf:hint ref="$form-resources/Category/Question1/hint"/>
<xf:alert ref="$form-resources/Category/Question1/alert"/>
<xf:itemset class="webforms-element webforms-answer"
ref="$form-resources/Category/Question1/item">
<xf:label ref="label"/>
<xf:value ref="value"/>
<xf:hint ref="hint"/>
</xf:itemset>
</xf:select1>
</xh:td>
</xh:tr>
<xh:tr>
<xh:td>
<xf:input bind="Question2-bind" class="webforms-element webforms-question"
id="Question2-control">
<xf:label mediatype="text/html" ref="$form-resources/Category/Question2/label"/>
<xf:hint ref="$form-resources/Category/Question2/hint"/>
<xf:alert ref="$form-resources/Category/Question2/alert"/>
</xf:input>
</xh:td>
</xh:tr>
<xh:tr>
<xh:td>
<xf:input bind="Question3-bind" class="webforms-element webforms-question"
id="Question3-control">
<xf:label mediatype="text/html" ref="$form-resources/Category/Question3/label"/>
<xf:hint ref="$form-resources/Category/Question3/hint"/>
<xf:alert ref="$form-resources/Category/Question3/alert"/>
</xf:input>
</xh:td>
</xh:tr>
<xh:tr>
<xh:td>
<xf:select1 appearance="full" bind="Question4-bind"
class="webforms-element webforms-question"
id="Question4-control">
<xf:label mediatype="text/html" ref="$form-resources/Category/Question4/label"/>
<xf:hint ref="$form-resources/Category/Question4/hint"/>
<xf:alert ref="$form-resources/Category/Question4/alert"/>
<xf:itemset class="webforms-element webforms-answer"
ref="$form-resources/Category/Question4/item">
<xf:label ref="label"/>
<xf:value ref="value"/>
<xf:hint ref="hint"/>
</xf:itemset>
</xf:select1>
</xh:td>
</xh:tr>
</fr:section>
</fr:body>
</fr:view>
</xh:body>
</xh:html>
有趣的是问题4,有相关规则(( xs:date($Question2) > xs:date('2015-05-20')) or ($Question1='Answer2'))
。
如果我先写xs:date($Question2) > xs:date('2015-05-20')
的部分,然后在OR运算符中写$Question1='Answer2'
的部分,当Question1
选择了Answer2
时,问题4不是显示。这意味着 OR 运算符的右侧部分将被忽略。但是,如果我将相关规则更改为 (( $Question1='Answer2') or (xs:date($Question2) > xs:date('2015-05-20')))
,则行为在两种情况下都完美无缺:如果 Question1 = answer 或日期字段具有正确的值,则会显示 Question4。
似乎将日期放在首位给我带来了一些问题。可能是因为如果Question3因流程不填,date为空值,相关规则运行不正确。
我也尝试了一些替代方法,例如检查添加 string-length(format-date($Question3), '[MNn,*-3]/[D01]/[Y]')) > 0
或 if(not(normalize-space($Question2) = '')) then ( xs:date($Question2) > xs:date('2015-05-20')) else false
的字段的长度,如果它是空的,则忽略日期字段运算符的处理范围。但一点运气都没有。
对于其他不同类型的日期,相关规则正常工作,因此我认为问题出在我的日期字段上。
如果这是预期的行为,问题是:如何以正确的方式使用日期字段以使相关规则正常工作?
首先,当 foo
是日期时,您不需要使用 xs:date($foo)
,type annotations enabled 现在是您在 Form Builder 中创建的表单的默认值。但这对你的情况没有多大帮助,因为当评估 $Question2 > xs:date('2015-05-20')
时,如果 $Question2
不是日期,整个表达式将失败,就像你写了 xs:date($Question2)
.所以在你的情况下,你需要:
- 首先在复选框上进行测试(您已经知道这行得通)。
- 写成
$Question2 castable as xs:date and $Question2 > xs:date('2015-05-20')
,这样当$Question2
不是日期时,这部分表达式不会失败,但 return 为 false。
我们已经看到这个问题的几个变体,我们目前认为我们可以通过将 XForms 引擎更改为 return 一个空序列来解决这个问题,当 $Question2
的输入值时被访问并且 $Question2
不是日期(或它应该是的任何类型)。这将等同于 () > xs:date('2015-05-20')
,其中 return 是错误的,并且适用于您的情况。如果您有兴趣,RFE 2251 中对此有更详细的介绍。但同样,现在,您将不得不求助于上述两种技术之一。