我有以下XML文档:
<ReportParameters SP="prRptActivityDetail">
<Parameter>
<Name>Period Start Date</Name>
<Type>Date</Type>
<Control>DateTextbox</Control>
<ControlName>dtePeriodStartDate</ControlName>
<Validators>
<Validator>Required</Validator>
<Validator>DataTypeCheck</Validator>
<Validator>StartBeforeEnd</Validator>
</Validators>
</Parameter>
</ReportParameters>
我编写了一个XSLT文件来转换上面的内容:
<xsl:for-each select="ReportParameters/Parameter/Validators">
<xsl:choose>
<xsl:when test="Validator='Required'">
<span>
<REQUIRED VALIDATOR CONTROL HERE>
</span>
</xsl:when>
<xsl:when test="Validator='DataTypeCheck'">
<span>
<DATA TYPE CHECK VALIDATOR CONTROL HERE>
</span>
</xsl:when>
</xsl:choose>
为清晰起见,我遗漏了很多XSLT。
对于每个参数控件(在这种情况下为Period Start Date)我希望列出所有验证器(在本例中为3)作为验证器控件放在页面上,但是我在使用for-each时只得到第一个验证器。我知道为什么这是,但我是xslt的完全新手,并且不知道解决这个问题的语法。
任何帮助非常感谢,
富
答案 0 :(得分:2)
我认为问题在于你正在循环'Validators'集合。您想要遍历'Validator'的所有实例。
尝试:(example I used in research)
<xsl:for-each select="ReportParameters/Parameter/Validators/Validator">
<xsl:choose>
<xsl:when test=".='Required'">
<span>
<REQUIRED VALIDATOR CONTROL HERE>
</span>
</xsl:when>
<xsl:when test=".='DataTypeCheck'">
<span>
<DATA TYPE CHECK VALIDATOR CONTROL HERE>
</span>
</xsl:when>
</xsl:choose>
答案 1 :(得分:1)
在学习XSLT时,最好知道应该避免使用<xsl:for-each>
,除非这确实是必要的。
这是一个简单而简短的“无环路”方式,以纯粹的推送方式实现相同的目标:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:variable name="vrtfValidatorNames">
<validator type="Required" name="REQUIRED"/>
<validator type="DataTypeCheck" name="DATA TYPE CHECK"/>
<validator type="StartBeforeEnd" name="START BEFORE END"/>
</xsl:variable>
<xsl:variable name="vValidatorNames" select=
"document('')/*/xsl:variable[@name='vrtfValidatorNames']/*"/>
<xsl:template match="Validator">
<<xsl:value-of select="$vValidatorNames[@type=current()]/@name"/> VALIDATOR CONTROL HERE>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
将此转换应用于提供的XML文档:
<ReportParameters SP="prRptActivityDetail">
<Parameter>
<Name>Period Start Date</Name>
<Type>Date</Type>
<Control>DateTextbox</Control>
<ControlName>dtePeriodStartDate</ControlName>
<Validators>
<Validator>Required</Validator>
<Validator>DataTypeCheck</Validator>
<Validator>StartBeforeEnd</Validator>
</Validators>
</Parameter>
</ReportParameters>
生成了想要的结果:
<REQUIRED VALIDATOR CONTROL HERE>
<DATA TYPE CHECK VALIDATOR CONTROL HERE>
<START BEFORE END VALIDATOR CONTROL HERE>
答案 2 :(得分:1)
我建议您将<xsl:for-each
代码替换为:
<xsl:apply-templates select="ReportParameters/Parameter/Validators/Validator" />
并为每个模板添加模板:
<xsl:template match="Validator[text()='Required']">
...
</xsl:template>
<xsl:template match="Validator[text()='DataTypeCheck']">
..
</xsl:template>
etc.
正如@kniemczak所说,你实际上只是在循环中通过父元素。
答案 3 :(得分:0)
对于此类任务,您无需显式循环元素。这不是XSLT的方式。在与树结构的匹配方面考虑更多。
这样的事情会起作用:
<xsl:if test="ReportParameters/Parameter/Validators/Validator='Required'">
<span>
<REQUIRED></REQUIRED>
</span>
</xsl:if>
<xsl:if test="ReportParameters/Parameter/Validators/Validator='DataTypeCheck'">
<span>
<DATA></DATA>
</span>
</xsl:if>
另请参阅创建子<xsl:template>
并使用<xsl:apply-templates>
调用它们来处理树的较小部分。对于大型变换,它应该更易于维护。