xslt转换列表并获取最大值



我想:

  1. 选择所有字符串值属性"foo",并将这些值存储在列表中
  2. 使用xslt中的一些映射将该列表中属性"foo"的每个值转换为一个数字
  3. 选择列表的最大值并输出

因此,给定以下xml:

<t>
    <tag foo="A">apples</tag>
    <tag foo="C">oranges</tag>
    <tag foo="B">trees</tag>
</t>

以及以下映射:

<xsl:variable name="myMap">
    <entry key="A">1</entry>
    <entry key="B">2</entry>
    <entry key="C">3</entry>
</xsl:variable>

输出为:

<max>3</max>

另一个问题是,为什么我不能缩进代码?我在放空位,但没用。

I这个标准的XSLT1.0转换(最像您的方法):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:variable name="vrtfMap">
  <entry key="A" value="1"/>
  <entry key="B" value="2"/>
  <entry key="C" value="3"/>
  <entry key="X" value="8"/>
 </xsl:variable>
 <xsl:variable name="vMap" select=
  "document('')/*/xsl:variable[@name = 'vrtfMap']/*"/>
 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>
 <xsl:template match="@foo">
  <xsl:attribute name="foo">
   <xsl:value-of select="$vMap[@key = current()]/@value"/>
  </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

当应用于以下XML文档时(因为您没有提供任何):

<t foo="X">
    <a foo="A">
        <b foo="B"/>
    </a>
    <c foo="C"/>
</t>

生成所需的正确结果

<t foo="8">
   <a foo="1">
      <b foo="2"/>
   </a>
   <c foo="3"/>
</t>

解释:适当使用XSLTcurrent()函数。


II。XSLT1.0解决方案,使用快捷键

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:key name="kValFromKey" match="entry/@value" use="../@key"/>
 <xsl:variable name="vrtfMap">
  <entry key="A" value="1"/>
  <entry key="B" value="2"/>
  <entry key="C" value="3"/>
  <entry key="X" value="8"/>
 </xsl:variable>
 <xsl:variable name="vMap" select=
  "document('')/*/xsl:variable[@name = 'vrtfMap']/*"/>
 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>
 <xsl:template match="@foo">
  <xsl:variable name="vCur" select="."/>
  <xsl:attribute name="foo">
   <xsl:for-each select="document('')">
    <xsl:value-of select="key('kValFromKey', $vCur)"/>
   </xsl:for-each>
  </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于同一XML文档(如上)时,会产生相同的正确结果

解释

  1. 使用<xsl:for-each select="document('')">将当前文档设置为样式表,以便key()函数将使用为此文档构建的键索引。

  2. 将模板匹配的节点保存在变量中,以便我们可以在xsl:for-each中使用它——这里不能正确使用current(),因为它获取xsl:for-each操作的当前节点。

更新:OP现在在一条评论中澄清说,他最大的问题是找到最大值。

<xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
     <xsl:variable name="vrtfMap">
      <entry key="A" value="1"/>
      <entry key="B" value="2"/>
      <entry key="C" value="3"/>
     </xsl:variable>
     <xsl:variable name="vMap" select=
      "document('')/*/xsl:variable[@name = 'vrtfMap']/*"/>
     <xsl:template match="/">
     <xsl:variable name="vDoc" select="."/>
      <xsl:variable name="vFoosMapped"
           select="$vMap[@key = $vDoc/*/*/@foo]"/>
      <max>
       <xsl:value-of select=
         "$vFoosMapped
            [not($vFoosMapped/@value > @value)]
              /@value
         "/>
      </max>
     </xsl:template>
</xsl:stylesheet>

如果给定此XML文档(OP提供的文档缺少一个singlelr-top元素):

<t>
    <tag foo="A">apples</tag>
    <tag foo="C">oranges</tag>
    <tag foo="B">trees</tag>
</t>

生成所需的正确结果

<max>3</max>

备注:在XSLT1.0中计算最大值(或最小值——以类似的方式)的一种更有效的方法是这样做:

<xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
     <xsl:variable name="vrtfMap">
      <entry key="A" value="1"/>
      <entry key="B" value="2"/>
      <entry key="C" value="3"/>
     </xsl:variable>
     <xsl:variable name="vMap" select=
      "document('')/*/xsl:variable[@name = 'vrtfMap']/*"/>
     <xsl:template match="/">
     <xsl:variable name="vDoc" select="."/>
      <xsl:variable name="vFoosMapped"
           select="$vMap[@key = $vDoc/*/*/@foo]"/>
      <max>
       <xsl:for-each select="$vFoosMapped">
         <xsl:sort select="@value" data-type="number" order="descending"/>
         <xsl:if test="position() = 1">
          <xsl:value-of select="@value"/>
         </xsl:if>
       </xsl:for-each>
      </max>
     </xsl:template>
</xsl:stylesheet>

另一个问题是,为什么我不能缩进代码?我在放空位,但是它不起作用。

这是一个他们几个月都没能修复的bug。

很可能您正在使用IE。如果您的版本是9,请执行以下操作

  1. 按F12。

  2. 在弹出的窗口中,点击最右边的菜单并选择:"文档模式:IE9标准"

现在,您应该能够看到带有缩进的代码。

相关内容

  • 没有找到相关文章

最新更新