【问题标题】:When inside for-each loop in xsl当在 xsl 的 for-each 循环中时
【发布时间】:2019-05-24 07:23:25
【问题描述】:

我有一个在 2 个不同级别中具有相同元素的 xml,我需要比较 2 个级别中元素的值并返回匹配元素的值。例如我有以下 xml

<root>
  <profiles>
    <profile>
     <Name>xxx</Name>
     <Gender>Male</Gender>
    </profile>
    <profile>
     <Name>yyy</Name>
     <Gender>Female</Gender>
    </profile>
  </profiles>
  <subroot>
    <profiles>
      <profile>
       <sName>xxx</sName>
       <sAge>10</sAge>
      </profile>
      <profile>
       <sName>yyy</sName>
       <sAge>20</sAge>
      </profile>
    </profiles>
  </subroot>
</root>

我需要为//root/subroot/profiles/profile 放置循环并获取Name,Age,Gender 元素的值。而我们必须通过将 name 元素值与 xpath //root/profiles/profile 进行比较来获取 Gender 元素的值。当我使用下面的代码时

  <xsl:for-each select="//root/subroot/profiles/profile">
    <xsl-for-each select="//root/profiles/profile">
      <xsl:choose>
       <xsl:when name=sname>
        <xsl:value-of select="Gender">
       </xsl:when>
      </xsl:choose>
    <xsl:for-each>
  </xsl-for-each>

当循环遍历第二个元素时,我得到了第一个元素的相应性别值,返回的第一个元素的相同值对于 xxx,yyy 都返回为“男性”。有人检查此代码并让我知道此问题的任何解决方法

【问题讨论】:

    标签: xslt xslt-1.0 xslt-2.0 xslt-grouping xslt-3.0


    【解决方案1】:

    我会使用 key 从相应的配置文件中查找数据 - 比如:

    XSLT 1.0

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:key name="subprofile" match="profile" use="sName" />
    
    <xsl:template match="/root">
        <xsl:copy>
            <xsl:for-each select="profiles/profile">
                <xsl:copy>
                    <xsl:copy-of select="*"/>
                    <xsl:copy-of select="key('subprofile', Name)/sAge"/>
                </xsl:copy>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
    
    </xsl:stylesheet>
    

    或者,如果您更喜欢另一个方向:

    XSLT 1.0

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:key name="profile" match="profile" use="Name" />
    
    <xsl:template match="/root">
        <xsl:copy>
            <xsl:for-each select="subroot/profiles/profile">
                <xsl:copy>
                    <xsl:copy-of select="key('profile', sName)/*"/>
                    <xsl:copy-of select="sAge"/>
                </xsl:copy>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
    
    </xsl:stylesheet>
    

    在这两种情况下,结果都是:

    结果

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
      <profile>
        <Name>xxx</Name>
        <Gender>Male</Gender>
        <sAge>10</sAge>
      </profile>
      <profile>
        <Name>yyy</Name>
        <Gender>Female</Gender>
        <sAge>20</sAge>
      </profile>
    </root>
    

    【讨论】:

    • 感谢您的回复。有没有其他方法使用 for-each 循环。例如,如果我只需要在输出中获取 元素
    • 当我尝试相同的代码时,输​​出低于输出 xxxMale10 profile> yyyFemaleFemale
    • 请编辑您的问题并在给定示例中显示您希望获得的准确输出。
    【解决方案2】:

    如@michael.hor257k 所述,最好使用键来处理许多连接查询,但更通用的方法是绑定变量:

    <xsl:for-each select="//root/subroot/profiles/profile">
      <xsl:variable name="outer-profile" select="."/>
      <xsl-for-each select="//root/profiles/profile">
         <xsl:variable name="inner-profile" select="."/>
          <xsl:choose>
           <xsl:when test="$outer-profile/x/y/z = $inner-profile/p/q/r">
            ...
           </xsl:when>
          </xsl:choose>
        <xsl:for-each>
      </xsl-for-each>
    

    【讨论】:

      猜你喜欢
      • 2012-10-11
      • 1970-01-01
      • 1970-01-01
      • 2015-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多