根据当前节点值有条件地匹配
时间:2020-03-05 18:53:11 来源:igfitidea点击:
给定以下XML:
<current> <login_name>jd</login_name> </current> <people> <person> <first>John</first> <last>Doe</last> <login_name>jd</login_name> </preson> <person> <first>Pierre</first> <last>Spring</last> <login_name>ps</login_name> </preson> </people>
如何从当前/登录匹配器中获取" John Doe"?
我尝试了以下方法:
<xsl:template match="current/login_name"> <xsl:value-of select="../people/first[login_name = .]"/> <xsl:text> </xsl:text> <xsl:value-of select="../people/last[login_name = .]"/> </xsl:template>
解决方案
回答
我认为他真正想要的是替换"当前"节点中的匹配项,而不是替换人节点中的匹配项:
<xsl:variable name="login" select="//current/login_name/text()"/> <xsl:template match="current/login_name"> <xsl:value-of select='concat(../../people/person[login_name=$login]/first," ", ../../people/person[login_name=$login]/last)'/> </xsl:template>
回答
我们想要current()
函数
<xsl:template match="current/login_name"> <xsl:value-of select="../../people/person[login_name = current()]/first"/> <xsl:text> </xsl:text> <xsl:value-of select="../../people/person[login_name = current()]/last"/> </xsl:template>
或者更干净一点:
<xsl:template match="current/login_name"> <xsl:for-each select="../../people/person[login_name = current()]"> <xsl:value-of select="first"/> <xsl:text> </xsl:text> <xsl:value-of select="last"/> </xsl:for-each> </xsl:template>
回答
只是为了增加我的想法
<xsl:template match="login_name[parent::current]"> <xsl:variable name="login" select="text()"/> <xsl:value-of select='concat(ancestor::people/child::person[login_name=$login]/child::first/text()," ",ancestor::people/child::person[login_name=$login]/child::last/text())'/> </xsl:template>
我总是喜欢在我的XPath中显式使用轴,更冗长但更清晰的恕我直言。
根据其余XML文档的外观(假设这只是一个片段),我们可能需要限制对" ancestor :: people"的引用,例如,使用" ancestor :: people [1]"来约束第一个人祖先。
回答
我将定义一个索引以索引人员:
<xsl:key name="people" match="person" use="login_name" />
在这里使用键只是保持代码干净,但是如果我们经常不得不根据其<login_name>子元素来检索<person>元素,那么我们可能还会发现它对效率有所帮助。
我有一个模板可以返回给定<person>
的格式名称:
<xsl:template match="person" mode="name"> <xsl:value-of select="concat(first, ' ', last)" /> </xsl:template>
然后我会做:
<xsl:template match="current/login_name"> <xsl:apply-templates select="key('people', .)" mode="name" /> </xsl:template>
回答
如果需要访问多个用户,那么JeniT的<xsl:key />
方法是理想的。
这是我的替代选择:
<xsl:template match="current/login_name"> <xsl:variable name="person" select="//people/person[login_name = .]" /> <xsl:value-of select="concat($person/first, ' ', $person/last)" /> </xsl:template>
我们将所选的<person>节点分配给变量,然后使用concat()函数输出名字/姓氏。
示例XML中也存在错误。 <person>
节点错误地以</ preson>
(typo)结尾
如果我们知道XML文档的整体结构(带有根节点等),则可以给出更好的解决方案。