具有嵌套元素的 XML 使用 XSLT v1.0 C# 进行过滤和计算

发布于 2024-10-14 15:30:17 字数 3298 浏览 2 评论 0原文

我有一个示例 xml 文件,其中 root 具有名称为“element”的元素。 该元素可以嵌套。

我想排除名称为“position”的元素,其中 “位置”值 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>

I have got a sample xml file where root has element with name "element".
This elements can be nested.

I would like to exclude elements with name "position" where
"position" value x = ("number" + "another") * count is greater than
average of sum(("number" + "another") * "count") from all "position" elements.

How to process this xml file with xslt v 1.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心是晴朗的。 2024-10-21 15:30:17

我将使用以下两遍方法

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

I would use the following two-pass approach:

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

when applied on the provided XML document:

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

the wanted, correct result is produced:

<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>
哀由 2024-10-21 15:30:17

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

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

Just for fun, this stylesheet without extensions:

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

Output:

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

Look how compact an XSLT 2.0 solution is:

<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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文