XML使用XSLT V1.0 C#进行计算的嵌套元素过滤
-
26-10-2019 - |
题
我有一个示例XML文件,其中root具有名称为“元素”的元素。该元素可以嵌套。
我想排除具有名称“位置”的元素,其中“位置”值x =(“ number” +“另一个”) *计数大于sum的平均值(((“ number” +“另一个”) *“ 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>
解决方案
我会使用以下两次通行方法:
<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>
其他提示
只是为了娱乐,此样式表没有扩展:
<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>
不隶属于 StackOverflow