我有一个 xml 文件,其中有两个元素“employeeID”和“managerID”。我喜欢检查 managerID 是否不存在于 employeeID 中的任何值中,然后将 managerID 的值替换为“未找到”。
如果 managerID 的值与 employeeID 中的任何值不匹配,我必须转换下面的 xml 并将第二个元素 managerID 的值替换为“Not Found”。
<wd:Report_Data xmlns:wd="urn:com.workday.report/bsvc">
<wd:Report_Entry>
<wd:employeeID>EMPLOYEE1</wd:employeeID>
<wd:managerID>EMPLOYEE5</wd:managerID>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:employeeID>EMPLOYEE2</wd:employeeID>
<wd:managerID>EMPLOYEE6</wd:managerID>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:employeeID>EMPLOYEE6</wd:employeeID>
<wd:managerID>EMPLOYEE17</wd:managerID>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:employeeID>EMPLOYEE17</wd:employeeID>
<wd:managerID>EMPLOYEE3</wd:managerID>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:employeeID>EMPLOYEE3</wd:employeeID>
<wd:managerID>EMPLOYEE2</wd:managerID>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:employeeID>EMPLOYEE4</wd:employeeID>
<wd:managerID>EMPLOYEE22</wd:managerID>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:employeeID>EMPLOYEE8</wd:employeeID>
<wd:managerID>EMPLOYEE2</wd:managerID>
</wd:Report_Entry>
</wd:Report_Data>
我的 xslt 如下所示,但每个人都返回“未找到”。预期结果应为
EMPLOYEE1,未找到
员工2,员工6
员工6,员工17
员工 17,员工 3
员工 3,员工 2
EMPLOYEE4,未找到
员工8,员工2
<?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:wd="urn:com.workday.report/bsvc"
xmlns:this="urn:this-stylesheet" exclude-result-prefixes="xs" version="2.0">
<xsl:output method="text"/>
<xsl:variable name="Delimiter" select="';'"/>
<xsl:variable name="Newline" select="'
'"/>
<xsl:variable name="allemployeesID">
<xsl:for-each select="/wd:Report_Data/Report_Entry">
<xsl:value-of select="wd:employeeID"/>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/">
<xsl:for-each select="wd:Report_Data/wd:Report_Entry">
<xsl:value-of select="wd:employeeID"/>
<xsl:value-of select="$Delimiter"/>
<xsl:choose>
<xsl:when test="contains($allemployeesID,wd:managerID)">
<xsl:value-of select="wd:managerID"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'Not Found'" />
</xsl:otherwise>
</xsl:choose>
<xsl:value-of select="$Newline"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
看起来只是一个打字错误:您在定义中的循环
wd
的 XPath 中缺少命名空间前缀。for-each
allemployeesID
即
Report_Entry
应该是wd:Report_Entry
更好:使用序列变量而不是字符串
但是我可以建议简化一下吗?您的变量可以只是员工标识符的序列,而不是让变量包含员工标识符的串联,然后使用函数
contains
搜索该字符串,您可以使用=
运算符进行搜索:更好的办法是,使用钥匙
注意:在上面的例子中,表达式
@test
将$allemployeesID = wd:managerID
搜索$allemployeesID
序列以找到与匹配的序列wd:managerID
,并且该搜索将是线性搜索。更好的方法是使用key
,它将使用索引搜索。如果输入数据文件很大,并且有很多员工,这可能会对运行时间产生相当大的影响。用来
xsl:key
代替allemployeesID
变量,并创建一个搜索索引,您可以使用key()
函数调用它。name
属性为搜索索引提供了一个名称。match
属性指定哪些节点将被索引(wd:employeeID
在本例中为所有元素)use
指定了您通过什么来查找它们。在这种情况下,.
意味着您使用其wd:employeeID
本身的值来查找它。通常,您会通过不同的值来查找某些内容,例如通过元素的某个属性的值来查找元素,但在这里,您只是查找它以查明它是否存在。要使用该密钥,请使用
key()
参数调用该函数:wd:employeeID
调用该函数的结果
key()
是wd:employeeID
元素本身(如果没有该值,则为空序列wd:employeeID
)。考虑将逻辑转移到 XPath 以减少
xsl
语句最后一件事更像是一种风格评论。我个人发现,在这样的工作中,实际上是传统的记录处理工作,例如您可能用 SQL 或 COBOL 编写,使用较少的
xsl
元素但使用更复杂的 XPath 表达式可能会更简单。XPath 的语法通常比等效的 XSLT 语句更简洁、更易读,因此当您不需要 XSLT 的模式匹配功能而可能需要使用时,这样做是值得的xsl:template
。例如: