我有一个xml文件,我尝试描述一些简单的用户界面,然后通过XSLT将其转换为带有XForms的有效html。我的意图是,这尽可能抽象,不应包含逻辑。但是使用XForms,您可以轻松地在多个控件之间进行绑定。我试图通过XSL转换来实现这个目标:
<structure>
<part class="TextInput" id="name"/>
<part class="TextOutput" id="nameOutput"/>
</structure>
<style>
<property part-name="name" name="label">Enter your name:</property>
<property part-name="nameOutput" name="label">Output name:</property>
</style>
<behavior>
<rule>
<condition>
<event part-name="name" class="binding"/>
</condition>
<action>
<property part-name="name" bind="name"/>
</action>
</rule>
<rule>
<condition>
<event part-name="nameOutput" class="binding"/>
</condition>
<action>
<property part-name="nameOutput" bind="name"/>
</action>
</rule>
</behavior>
所以基本上,我这样描述 - 我有rule
说明哪个part
将绑定到其他part
(所有部分都有唯一ids
- 在这种情况下name
和nameOuput
)。换句话说,在这个xml中我有2个部分,我想在每个部分中添加一个属性来定义可能的绑定。这是我无法弄清楚该怎么做......
这应该是有效输出:
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<head>
<title>Test</title>
<xf:model>
<xf:instance xmlns="">
<data>
<name/>
</data>
</xf:instance>
<xf:bind id="name" nodeset="/data/name"/>
</xf:model>
</head>
<body>
<xf:input id="name" ref="name" bind="name">
<xf:label>Enter your name:</xf:label>
</xf:input>
<xf:output id="name" ref="name" bind="name">
<xf:label>Output name:</xf:label>
</xf:output>
</body>
</html>
我现在到了这里:
.......
<body>
<xf:input id="name" ref="name">
<xf:label>Enter your name:</xf:label>
</xf:input>
<xf:output id="name" ref="name">
<xf:label>Output name:</xf:label>
</xf:output>
</body>
......
我实现了其他一切,除了我必须包含必须绑定到<xf:input>
和<xf:output>
元素作为属性(<xf:input bind="name">
)的实例的部分。如您所见,缺少bind="part-name"
属性。
我已将XSLT分发到不同的文件中以提高可读性/可维护性,但这里只负责转换为<xf:input>
- 我想它应该足够了,但如果需要我可以分享其他文件。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xf="http://www.w3.org/2002/xforms"
exclude-result-prefixes="xs"
version="2.0">
<xsl:key name="textLabels" match="property[@name='label']" use="@part-name"/>
<xsl:template match="part[@class='TextInput'][key('textLabels', @id)]">
<xf:input>
<xsl:apply-templates select="@size | @style | @id"/>
<!-- Create Reference to the XForms instance -->
<xsl:attribute name="ref">
<xsl:choose>
<xsl:when test="@id">
<xsl:value-of select="@id"/>
</xsl:when>
<xsl:when test="@name and not(@id)">
<xsl:value-of select="@name"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(local-name(.), position())"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:for-each select="behavior/rule/condition/event[@class='binding']">
<xsl:attribute name="bind">
<xsl:value-of select="@part-name"/>
</xsl:attribute>
</xsl:for-each>
<xf:label>
<xsl:value-of select="key('textLabels', @id)"/>
</xf:label>
</xf:input>
</xsl:template>
</xsl:stylesheet>
那么如何在behavior / rule / action / property [@bind]中添加属性的值?在此先感谢:)
答案 0 :(得分:1)
我认为问题在于这一行
<xsl:for-each select="behavior/rule/condition/event[@class='binding']">
这导致两个问题。首先,它是一个相对的xpath表达式;相对于您所在的节点。在这种情况下,部分元素。但行为不是 part 的孩子,所以表达式不匹配!
其次,您正在查看所有规则元素,当我认为您只需要找到具有匹配部分名称的那个元素时。
要解决这个问题,您可以做的是首先定义一个键,通过绑定部件名称来查找规则元素
<xsl:key name="bindings" match="rule" use="condition/event[@class='binding']/@part-name"/>
然后,要在 xf:input 元素上创建 bind 属性,只需将现有的 xsl:for-each 替换为:
<xsl:attribute name="bind">
<xsl:value-of select="key('bindings', @id)/action/property/@bind"/>
</xsl:attribute>