gpt4 book ai didi

Xslt, Xpath 以一对二对子节点进行分组

转载 作者:行者123 更新时间:2023-12-03 17:38:15 25 4
gpt4 key购买 nike

我有以下 XML:
(纸上的 child 可以是我现阶段不知道的任何节点名称)

<catalog>
<Paper result="false">Paper1</Paper>
<Books result="true">Books1</Books>
<Books result="true">Books2</Books>
<Books result="true">Books3</Books>
<Books result="true">Books4</Books>
<Paper result="false">Paper2</Paper>
<Books result="false">Books5</Books>
<Paper result="false">Paper3</Paper>
<Books result="true">Books6</Books>
<Books result="true">Books7</Books>
<Books result="false">Books8</Books>
<Paper result="false">Paper4</Paper>
<Paper result="false">Paper5</Paper>
<Books result="true">Books9</Books>
<Books result="true">Books10</Books>
<Books result="true">Books11</Books>
<Books result="true">Books12</Books>
<Books result="true">Books13</Books>
<Books result="true">Books14</Books>
<Books result="false">Books15</Books>
</catalog>

我试着把这些书分成两组。
在 XML 中,您会看到所需 Xpath 的预期结果。

到目前为止,我的 Xslt (1.0) 有点大并且没有真正工作:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table border="1">
<tr bgcolor="#9acd32">
<th>RESULT</th>
</tr>

<xsl:for-each select="catalog/child::*">
<tr>
<td>

<xsl:value-of select="."/> |
<xsl:value-of select="@result"/> =

<xsl:value-of select="( self::Books and following-sibling::*[1][self::Books] ) or
( self::Books and preceding-sibling::*[1][self::Books] and not( following-sibling::*[1][self::Books] ) and not( preceding-sibling::*[position()=2][self::Books] ) ) or
( self::Books and preceding-sibling::*[1][self::Books] and preceding-sibling::*[position()=1][self::Books] and preceding-sibling::*[position()=2][self::Books] and preceding-sibling::*[position()=3][self::Books] ) " />

</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

Xpath (1.0) 逻辑是静态的,需要在书籍数量方面更加灵活。

结果:
Paper1  | false = false
Books1 | true = true
Books2 | true = true
Books3 | true = true
Books4 | true = true
Paper2 | false = false
Books5 | false = false
Paper3 | false = false
Books6 | true = true
Books7 | true = true
Books8 | false = false
Paper4 | false = false
Paper5 | false = false
Books9 | true = true
Books10 | true = true
Books11 | true = true
Books12 | true = true
Books13 | true = true
Books14 | true = true
Books15 | false = true

如您所见,Books15 的结果并不像预期的那样。

我可以扩展我的逻辑并添加 7+ Books 的案例,但这不是一个好方法。

另一种方法是计算前面的 Books 并根据 mod 2 检查它们是否为偶数。因此,我知道当前书籍是否可以与前一本书分组。但是,由于我不知道其他子节点的名称或值,我正在努力获得 Books 和其他子节点之间的计数。

任何人都有一个很好的方法来将 n 个子节点分成一组吗?

由于我在有限的 XSLT 环境中工作,因此我不能使用键或更改 foreach,因为它需要遍历所有我不知道的子节点。

非常感谢您的帮助。

干杯

更新

对不起,我认为我的解释足以解决主要问题,所以我可以自己解决剩下的问题。无论如何,所需的 XML 最终结果输出应如下所示:
<table>
<tr><td>Paper1</td></tr>
</table>

<table>
<tr><td>Books1</td></tr>
<tr><td>Books2</td></tr>
</table>

<table>
<tr><td>Books3</td></tr>
<tr><td>Books4</td></tr>
</table>

<table>
<tr><td>Paper2</td></tr>
</table>

<table>
<tr><td>Books5</td></tr>
</table>

<table>
<tr><td>Paper3</td></tr>
</table>

<table>
<tr><td>Books6</td></tr>
<tr><td>Books7</td></tr>
</table>

<table>
<tr><td>Books8</td></tr>
</table>

<table>
<tr><td>Paper4</td></tr>
</table>

<table>
<tr><td>Books9</td></tr>
<tr><td>Books10</td></tr>
</table>

<table>
<tr><td>Books11</td></tr>
<tr><td>Books12</td></tr>
</table>

<table>
<tr><td>Books13</td></tr>
<tr><td>Books14</td></tr>
</table>

<table>
<tr><td>Books15</td></tr>
</table>

如您所见,只要有可能的“候选人”可以分组,这些书就会按两对组合在一起。 Books5、Books8 和 Books15 是单独的,因为没有直接高于或低于符合分组标准的 Books 子级,因为中间还有另一个子级。

同样,我不知道其他子节点是什么(在这种情况下是纸),所以我不能使用它们的名称、属性或内容来匹配。

最佳答案

这并不像我一开始错误地认为的那么微不足道。尝试:

XSLT 1.0

<?xml version="1.0" encoding="UTF-8"?>
<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:key name="grpOfBooks" match="Books" use="count(preceding-sibling::*[not(self::Books)])" />

<xsl:template match="/catalog">
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="catalog/*[not(self::Books)]">
<table>
<tr>
<td><xsl:value-of select="."/></td>
</tr>
</table>
</xsl:template>

<xsl:template match="Books [count(. | key('grpOfBooks', count(preceding-sibling::*[not(self::Books)]))[1]) = 1]">
<xsl:for-each select="key('grpOfBooks',count(preceding-sibling::*[not(self::Books)]))[position() mod 2 = 1] ">
<table>
<tr>
<td><xsl:value-of select="."/></td>
<xsl:if test="following-sibling::*[1][self::Books]">
<td><xsl:value-of select="following-sibling::Books[1]"/></td>
</xsl:if>
</tr>
</table>
</xsl:for-each>
</xsl:template>

<xsl:template match="Books"/>

</xsl:stylesheet>

编辑:

这是同样的事情,在不使用 key 的情况下实现(效率较低!):
<?xml version="1.0" encoding="UTF-8"?>
<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:template match="/catalog">
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="catalog/*[not(self::Books)]">
<table>
<tr>
<td><xsl:value-of select="."/></td>
</tr>
</table>
</xsl:template>

<xsl:template match="Books[not(preceding-sibling::*[1][self::Books])]">
<xsl:variable name="grp" select="count(preceding-sibling::*[not(self::Books)])" />
<xsl:for-each select="(. | following-sibling::Books) [count(preceding-sibling::*[not(self::Books)])=$grp] [position() mod 2 = 1] ">
<table>
<tr>
<td><xsl:value-of select="."/></td>
<xsl:if test="following-sibling::*[1][self::Books]">
<td><xsl:value-of select="following-sibling::Books[1]"/></td>
</xsl:if>
</tr>
</table>
</xsl:for-each>
</xsl:template>

<xsl:template match="Books"/>

</xsl:stylesheet>

关于Xslt, Xpath 以一对二对子节点进行分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24110624/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com