【问题标题】:Match conditionally upon current node value根据当前节点值有条件地匹配
【发布时间】:2010-09-08 21:16:22
【问题描述】:

给定以下 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>

【问题讨论】:

    标签: xslt xpath xmlnode


    【解决方案1】:

    我会定义一个键来索引人员:

    <xsl:key name="people" match="person" use="login_name" />
    

    在此处使用键只会保持代码整洁,但如果您经常需要根据 &lt;login_name&gt; 子元素检索 &lt;person&gt; 元素,您可能会发现它有助于提高效率。

    我有一个模板,它返回给定&lt;person&gt; 的格式化名称:

    <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>
    

    【讨论】:

    • 好吧,再往下忽略我的回答,这个很棒。清洁并由漂亮的可重复使用部件组成。
    【解决方案2】:

    你想要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>
    

    【讨论】:

    • 感谢当前的提示...即使我真的不喜欢在 xslt 中使用 for-each ...
    【解决方案3】:

    如果您需要访问多个用户,那么JeniT's &lt;xsl:key /&gt; approach 是理想的选择。

    这是我的另一种看法:

    <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>
    

    我们将选定的&lt;person&gt; 节点分配给一个变量,然后我们使用concat() 函数输出名字/姓氏。

    您的示例 XML 中也存在错误。 &lt;person&gt; 节点错误地以 &lt;/preson&gt; 结尾(错字)

    如果我们知道 XML 文档的整体结构(包括根节点等),可以给出更好的解决方案

    【讨论】:

    • 感谢您的提示...效果很好...我不知道为什么,我只是不喜欢在 xslt 中使用变量...
    【解决方案4】:

    我认为他真正想要的是匹配中“当前”节点的替换,而不是人员节点中的匹配:

    <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>
    

    【讨论】:

      【解决方案5】:

      只是将我的想法添加到堆栈中

      <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]”来限制第一个人的祖先。

      【讨论】:

        猜你喜欢
        • 2018-08-20
        • 1970-01-01
        • 2023-03-16
        • 2013-03-27
        • 2015-01-07
        • 1970-01-01
        • 1970-01-01
        • 2012-12-28
        • 1970-01-01
        相关资源
        最近更新 更多