【问题标题】:XML with nested elements filtering with calculation using XSLT v1.0 C#带有嵌套元素的 XML 使用 XSLT v1.0 C# 进行计算过滤
【发布时间】:2011-01-27 20:31:24
【问题描述】:

我有一个示例 xml 文件,其中根有名为“元素”的元素。 这个元素可以嵌套。

我想排除名称为“位置”的元素,其中 "位置" 值 x = ("数字" + "另一个") * 计数大于 所有 "position" 元素的 sum(("number" + "another") * "count") 的平均值。

如何使用 xslt v 1 处理这个 xml 文件。

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <element>
    <position>
      <number>
        1
      </number>
      <another>
        2
      </another>
      <count>
        3
      </count>
    </position>
    <position>
      <number>
        3
      </number>
      <another>
        1
      </another>
      <count>
        5
      </count>
    </position>
    <element>
      <position>
        <number>
          3
        </number>
        <another>
          3
        </another>
        <count>
          5
        </count>
      </position>
      <position>
        <number>
          3
        </number>
        <another>
          6
        </another>
        <count>
          5
        </count>
      </position>
      <element>
        <position>
          <number>
            3
          </number>
          <another>
            3
          </another>
          <count>
            5
          </count>
        </position>
        <position>
          <number>
            3
          </number>
          <another>
            7
          </another>
          <count>
            5
          </count>
        </position>
        <element>
          <position>
            <number>
              33
            </number>
            <another>
              4
            </another>
            <count>
              5
            </count>
          </position>
          <position>
            <number>
              34
            </number>
            <another>
              3
            </another>
            <count>
              5
            </count>
          </position>
        </element>
      </element>
    </element>
  </element>
  <element>
    <position>
      <number>
        5
      </number>
      <another>
        1
      </another>
      <count>
        2
      </count>
    </position>
    <position>
      <number>
        3
      </number>
      <another>
        3
      </another>
      <count>
        9
      </count>
    </position>
    <element>
      <position>
        <number>
          5
        </number>
        <another>
          3
        </another>
        <count>
          2
        </count>
      </position>
      <position>
        <number>
          3
        </number>
        <another>
          3
        </another>
        <count>
          5
        </count>
      </position>
    </element>
  </element>
</root>

【问题讨论】:

    标签: xml xslt xslt-1.0 xslcompiledtransform


    【解决方案1】:

    我会使用以下两遍方法:

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
     <xsl:output omit-xml-declaration="yes"/>
    
     <xsl:variable name="vrtfPass1">
      <xsl:apply-templates select="/*" mode="getScore"/>
     </xsl:variable>
    
     <xsl:variable name="vPass1" select="ext:node-set($vrtfPass1)/*"/>
    
     <xsl:variable name="vAverage" select=
      "sum($vPass1//position/@score) div count($vPass1//position)"/>
    
     <xsl:template match="node()|@*" name="identity" mode="getScore">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*" mode="getScore"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template  match="node()|@*">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match="/">
      <xsl:apply-templates select="$vPass1"/>
     </xsl:template>
    
     <xsl:template match="position" mode="getScore">
      <position score="{(number + another)*count}">
        <xsl:apply-templates mode="getScore"/>
      </position>
     </xsl:template>
    
     <xsl:template match="position">
      <xsl:if test="not(@score > $vAverage)">
       <position>
        <xsl:apply-templates mode="getScore"/>
       </position>
      </xsl:if>
     </xsl:template>
    </xsl:stylesheet>
    

    应用于提供的 XML 文档时:

    <root>
        <element>
            <position>
                <number>1</number>
                <another>2</another>
                <count>3</count>
            </position>
            <position>
                <number>3</number>
                <another>1</another>
                <count>5</count>
            </position>
            <element>
                <position>
                    <number>3</number>
                    <another>3</another>
                    <count>5</count>
                </position>
                <position>
                    <number>3</number>
                    <another>6</another>
                    <count>5</count>
                </position>
                <element>
                    <position>
                        <number>3</number>
                        <another>3</another>
                        <count>5</count>
                    </position>
                    <position>
                        <number>3</number>
                        <another>7</another>
                        <count>5</count>
                    </position>
                    <element>
                        <position>
                            <number>33</number>
                            <another>4</another>
                            <count>5</count>
                        </position>
                        <position>
                            <number>34</number>
                            <another>3</another>
                            <count>5</count>
                        </position>
                    </element>
                </element>
            </element>
        </element>
        <element>
            <position>
                <number>5</number>
                <another>1</another>
                <count>2</count>
            </position>
            <position>
                <number>3</number>
                <another>3</another>
                <count>9</count>
            </position>
            <element>
                <position>
                    <number>5</number>
                    <another>3</another>
                    <count>2</count>
                </position>
                <position>
                    <number>3</number>
                    <another>3</another>
                    <count>5</count>
                </position>
            </element>
        </element>
    </root>
    

    产生想要的正确结果:

    <root>
        <element>
            <position>
                <number>1</number>
                <another>2</another>
                <count>3</count>
            </position>
            <position>
                <number>3</number>
                <another>1</another>
                <count>5</count>
            </position>
            <element>
                <position>
                    <number>3</number>
                    <another>3</another>
                    <count>5</count>
                </position>
                <position>
                    <number>3</number>
                    <another>6</another>
                    <count>5</count>
                </position>
                <element>
                    <position>
                        <number>3</number>
                        <another>3</another>
                        <count>5</count>
                    </position>
                    <position>
                        <number>3</number>
                        <another>7</another>
                        <count>5</count>
                    </position>
                    <element>
    
    
                    </element>
                </element>
            </element>
        </element>
        <element>
            <position>
                <number>5</number>
                <another>1</another>
                <count>2</count>
            </position>
            <position>
                <number>3</number>
                <another>3</another>
                <count>9</count>
            </position>
            <element>
                <position>
                    <number>5</number>
                    <another>3</another>
                    <count>2</count>
                </position>
                <position>
                    <number>3</number>
                    <another>3</another>
                    <count>5</count>
                </position>
            </element>
        </element>
    </root>
    

    【讨论】:

    • 我忘记添加我使用 XslCompiledTransform 类是否可以应用您的方法?
    • tkachenko.com/blog/archives/000714.html 我对 Dimitre 的评论的附录
    • @marcinn:是的,我总是在多个 XSLT 处理器上测试我的解决方案,而且几乎总是其中一个是 XslCompiledTransform。是的,这个转换是使用 XslCompiledTransform 执行的。
    【解决方案2】:

    只是为了好玩,这个没有扩展的样式表:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:variable name="vAvgPosition">
            <xsl:apply-templates select="/descendant::position[1]"
                                 mode="avgPosition"/>
        </xsl:variable>
        <xsl:template match="node()|@*" name="identity">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:copy>
        </xsl:template>
        <xsl:template match="position" mode="avgPosition">
            <xsl:param name="pSum" select="0"/>
            <xsl:param name="pCount" select="0"/>
            <xsl:variable name="vSum"
                          select="$pSum + (number + another) * count"/>
            <xsl:variable name="vCount" select="$pCount + 1"/>
            <xsl:variable name="vNext" select="following::position[1]"/>
            <xsl:apply-templates select="$vNext" mode="avgPosition">
                <xsl:with-param name="pSum" select="$vSum"/>
                <xsl:with-param name="pCount" select="$vCount"/>
            </xsl:apply-templates>
            <xsl:if test="not($vNext)">
                <xsl:value-of select="$vSum div $vCount"/>
            </xsl:if>
        </xsl:template>
        <xsl:template match="position">
            <xsl:if test="not((number + another) * count > $vAvgPosition)">
                <xsl:call-template name="identity"/>
            </xsl:if>
        </xsl:template>
    </xsl:stylesheet>
    

    输出:

    <root>
        <element>
            <position>
                <number>1</number>
                <another>2</another>
                <count>3</count>
            </position>
            <position>
                <number>3</number>
                <another>1</another>
                <count>5</count>
            </position>
            <element>
                <position>
                    <number>3</number>
                    <another>3</another>
                    <count>5</count>
                </position>
                <position>
                    <number>3</number>
                    <another>6</another>
                    <count>5</count>
                </position>
                <element>
                    <position>
                        <number>3</number>
                        <another>3</another>
                        <count>5</count>
                    </position>
                    <position>
                        <number>3</number>
                        <another>7</another>
                        <count>5</count>
                    </position>
                    <element></element>
                </element>
            </element>
        </element>
        <element>
            <position>
                <number>5</number>
                <another>1</another>
                <count>2</count>
            </position>
            <position>
                <number>3</number>
                <another>3</another>
                <count>9</count>
            </position>
            <element>
                <position>
                    <number>5</number>
                    <another>3</another>
                    <count>2</count>
                </position>
                <position>
                    <number>3</number>
                    <another>3</another>
                    <count>5</count>
                </position>
            </element>
        </element>
    </root>
    

    看看 XSLT 2.0 解决方案有多紧凑:

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:variable name="vAvgPosition"
             select="avg(//position/((number+another)*count))"/>
        <xsl:template match="node()|@*">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:copy>
        </xsl:template>
        <xsl:template match="position[(number+another)*count > $vAvgPosition]"/>
    </xsl:stylesheet>
    

    【讨论】:

      猜你喜欢
      • 2014-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多