如何在XSLT中检查字段值、比较及处理多元素嵌套场景?
嘿,我来帮你搞定这几个XSLT的问题,咱们一步步拆解:
1. 用if语句检查字段值并做比较
在XSLT里,<xsl:if>是做条件判断的核心工具,通过test属性写判断逻辑就行。不管是比较字符串、数值,还是检查元素是否满足特定条件,都可以这么玩:
比如要检查status元素值等于"active",或者count数值大于10:
<!-- 字符串匹配判断 --> <xsl:if test="status = 'active'"> <active-mark>Yes</active-mark> </xsl:if> <!-- 数值大小比较 --> <xsl:if test="count > 10"> <high-count-tag>True</high-count-tag> </xsl:if>
test属性里的语法和XPath一致,你可以用=、!=、>、<这些运算符,还能结合and/or写复合判断逻辑。
2. 验证purpose元素是否存在,存在则取值否则忽略
要判断元素是否存在,直接在test里写元素路径就行——只要路径能匹配到元素,条件就为真。比如处理当前节点下的purpose元素:
<!-- 只有purpose存在时,才生成对应节点并取值 --> <xsl:if test="purpose"> <extracted-purpose> <xsl:value-of select="purpose"/> </extracted-purpose> </xsl:if>
如果XML里没有purpose元素,这段代码就不会生成extracted-purpose节点,自动忽略掉,完全符合你的需求。
3. 在if条件内嵌套for-each处理多元素数组(purposeMessage)
你之前尝试没成功,大概率是路径写错了或者结构没捋顺。咱们结合前面的条件判断,把for-each嵌套在if里面,确保只有purpose存在时,才去循环处理purposeMessage:
假设你的XML结构是这样的:
<item> <purpose>User Feedback</purpose> <purposeMessage>Page loads too slow</purposeMessage> <purposeMessage>UI navigation is confusing</purposeMessage> </item>
对应的XSLT代码可以这么写:
<xsl:if test="purpose"> <!-- 先输出purpose的值 --> <purpose-text><xsl:value-of select="purpose"/></purpose-text> <!-- 循环每个purposeMessage,生成对应数量的内部元素 --> <message-group> <xsl:for-each select="purposeMessage"> <single-message> <xsl:value-of select="."/> </single-message> </xsl:for-each> </message-group> </xsl:if>
如果purposeMessage是嵌套在purpose内部的(比如<purpose><purposeMessage>...</purposeMessage></purpose>),那select路径要改成purpose/purposeMessage,别写错路径哦!
完整示例(XML+XSLT)
为了让你更清楚,给个完整的可运行例子:
输入XML
<root> <item> <purpose>Bug Report</purpose> <purposeMessage>Crash on login</purposeMessage> <purposeMessage>Error when saving form</purposeMessage> </item> <item> <name>Normal Content</name> <!-- 这里没有purpose元素 --> </item> <item> <purpose>Feature Request</purpose> <!-- 这里有purpose但没有purposeMessage --> </item> </root>
处理用的XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/root"> <processed-result> <xsl:apply-templates select="item"/> </processed-result> </xsl:template> <xsl:template match="item"> <processed-item> <!-- 检查purpose是否存在 --> <xsl:if test="purpose"> <purpose-content><xsl:value-of select="purpose"/></purpose-content> <!-- 循环处理每个purposeMessage --> <message-list> <xsl:for-each select="purposeMessage"> <msg><xsl:value-of select="."/></msg> </xsl:for-each> </message-list> </xsl:if> </processed-item> </xsl:template> </xsl:stylesheet>
输出结果
<processed-result> <processed-item> <purpose-content>Bug Report</purpose-content> <message-list> <msg>Crash on login</msg> <msg>Error when saving form</msg> </message-list> </processed-item> <processed-item> <!-- 没有purpose,所以无额外节点 --> </processed-item> <processed-item> <purpose-content>Feature Request</purpose-content> <message-list> <!-- 没有purposeMessage,所以message-list为空 --> </message-list> </processed-item> </processed-result>
这样就能完美实现你要的效果:只有purpose存在时才处理,有多少个purposeMessage就生成多少个对应的内部元素。
内容的提问来源于stack exchange,提问作者Neo

