我试图根据数据(包含在实例“i-rec”中)和一系列约束(包含在实例“i-schemaConstraints”中)来限制项目集中的项目。本质上,如果 i-rec 中有一定数量的元素,那么该选项将不再显示在下拉菜单中,这是基于 i-schemaConstraints 实例中的元素。到目前为止,我还没有找到一种方法将它们与 XPath 结合在一起。是否可以?我正在使用 XSLTForms 版本 1.3。
我尝试过以下方法:
<xf:itemset ref="instance('i-schemaConstraints')/*[local-name() = local-name(current())][1]/*:childElements[1]/descendant-or-self::*:element[count(@ident[. = current()/child::*/local-name()]) < instance('i-schemaConstraints')/*[local-name() = local-name(current())][1]/*:childElements[1]//*:element/@maxOccurs]">
<xf:label ref="@label"/>
<xf:value ref="@ident"/>
</xf:itemset>
完整的 XForm 代码如下:
<?xml-stylesheet href="xsl/xsltforms.xsl" type="text/xsl"?>
<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" xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:tei="http://www.tei-c.org/ns/1.0">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Bug Demo</title>
<xf:model xmlns="http://www.w3.org/2002/xforms" id="m-mss">
<xf:instance id="i-rec">
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<titleStmt>
<title/>
<title/>
<title/>
</titleStmt>
</TEI>
</xf:instance>
<xf:instance id="i-availableElements">
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<titleStmt/>
<title/>
<author/>
</TEI>
</xf:instance>
<xf:instance id="i-schemaConstraints">
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<titleStmt ident="titleStmt" elementName="titleStmt" elementLabel="Title Statment">
<childElements>
<element ident="title" label="title" minOccurs="1" maxOccurs="2"/>
<element ident="author" label="author" minOccurs="0" maxOccurs="2"/>
</childElements>
</titleStmt>
<title ident="title" elementName="title" elementLabel="Title Element"/>
<author ident="author" elementName="author" elementLabel="Author Element"/>
</TEI>
</xf:instance>
<xf:instance id="i-insert-elements">
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<element/>
</TEI>
</xf:instance>
<xf:bind id="elementRules" nodeset="instance('i-rec')//*:titleStmt/*:title" constraint="count(instance('i-rec')//*:titleStmt/*:title) <= 2"/>
</xf:model>
</head>
<body>
<h2>Debug restrictions </h2>
<!-- Main element -->
<xf:repeat xmlns="http://www.w3.org/2002/xforms" ref="instance('i-rec')//tei:titleStmt"
id="titleStmtLevel1">
<div xmlns="http://www.w3.org/1999/xhtml"
style="margin:12px; padding:12px; border:1px solid #ccc;">
<!-- Element Label --> TitleStmt
<!-- Select1 to add available elements -->
<xf:select1 xmlns="http://www.w3.org/2002/xforms"
ref="instance('i-availableElements')/*[local-name() = local-name(current())]">
<xf:label/>
<xf:itemset
ref="instance('i-schemaConstraints')/*[local-name() = local-name(current())][1]/*:childElements[1]/descendant-or-self::*:element
[count(@ident[. = current()/child::*/local-name()]) < instance('i-schemaConstraints')/*[local-name() = local-name(current())][1]/*:childElements[1]//*:element/@maxOccurs]">
<xf:label ref="@label"/>
<xf:value ref="@ident"/>
</xf:itemset>
<xf:action ev:event="xforms-value-changed">
<xf:setvalue ref="instance('i-insert-elements')//*:element"
value="instance('i-availableElements')/*[local-name() = local-name(current())]"
/>
</xf:action>
</xf:select1>
<xf:trigger class="btn btn-outline-secondary btn-sm controls add" appearance="full">
<xf:label><i class="bi bi-plus-circle"></i> Add element </xf:label>
<xf:insert ev:event="DOMActivate" context="." at="."
origin="instance('i-availableElements')/*[local-name() = instance('i-insert-elements')//*:element][1]"
position="after"/>
<xf:setvalue ev:event="DOMActivate" ref="instance('i-insert-elements')//*:element"/>
<xf:setvalue ev:event="DOMActivate"
ref="instance('i-availableElements')/*[local-name() = local-name(current())][instance('i-schemaConstraints')/*[local-name() = local-name(current())]/*:childElements[1]/*:child/*:element]"
/>
</xf:trigger>
<div> Element Value: <xf:input xmlns="http://www.w3.org/2002/xforms"
ref=".[not(instance('i-schemaConstraints')/*[local-name() = local-name(current())][1]/*:controlledValues) and instance('i-schemaConstraints')/*[local-name() = local-name(current())][1]/*:childElements/*:textNode[@type='input']]">
<xf:alert>Error: No more than 2</xf:alert>
</xf:input>
<!-- Child elements -->
<xf:repeat xmlns="http://www.w3.org/2002/xforms"
id="additionalGrpRepeatLevel11GrpRepeatLevel1" ref="./*">
<div xmlns="http://www.w3.org/1999/xhtml"
style="margin:12px; padding:12px; border:1px solid #ccc;">
<xf:trigger xmlns="http://www.w3.org/2002/xforms" appearance="minimal" ref="."
><xf:label>x</xf:label>
<xf:delete ev:event="DOMActivate" ref="."/>
</xf:trigger>
<!-- Element Label --> level 2 <xf:output
value="instance('i-schemaConstraints')/*[local-name() = local-name(current())][1]/@elementLabel"
/> Element Value: <xf:input
ref=".[not(instance('i-schemaConstraints')/*[local-name() = local-name(current())][1]/*:controlledValues) and instance('i-schemaConstraints')/*[local-name() = local-name(current())][1]/*:childElements/*:textNode[@type='input']]">
<xf:alert>Error: No more than 1 title allowed here</xf:alert>
</xf:input>
</div>
</xf:repeat>
</div>
</div>
</xf:repeat>
</body>
</html>
您实际上想要转换
childElements
中的
i-schemaConstraints
<titleStmt>
<childElements>
<element ident="title" label="title" minOccurs="1" maxOccurs="2" />
<element ident="author" label="author" minOccurs="0" maxOccurs="2" />
</childElements>
</titleStmt>
进入绑定约束
<xf:bind
nodeset="instance('i-rec')//titleStmt"
constraint="count(title) >= 1 and count(title) <= 2" />
<xf:bind
nodeset="instance('i-rec')//titleStmt"
constraint="count(author) >= 0 and count(author) <= 2" />
由于这些绑定约束必须在模型的每次更改时进行评估,因此不在运行时动态评估它们,而是在启动 XForms 处理器之前将其转换为
xf:bind
元素once肯定是值得的。 (我假设 i-schemaConstraints
在运行时不会改变。)
以下 XSLT 1.0 转换可应用于 XForms 文档并插入必要的
xf:bind
元素。
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xf="http://www.w3.org/2002/xforms" version="1.0">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="xf:model">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
<xsl:apply-templates
select="xf:instance[@id='i-schemaConstraints']//childElements/element"
mode="bind" />
</xsl:copy>
</xsl:template>
<xsl:template match="element" mode="bind">
<xf:bind nodeset="instance('i-rec')//{../../@ident}"
constraint="count({@ident}) >= {@minOccurs} and count({@ident}) <= {@maxOccurs}" />
</xsl:template>
</xsl:stylesheet>