xml - XSLT 忽略重复元素

标签 xml xslt xpath

我刚开始学习 XSLT,在忽略重复元素时遇到了麻烦。

我一直在搜索 Stack Overflow,看到有人问过类似的问题。我尝试了一个小例子来查看我的文件哪里出了问题,并且能够忽略重复的元素。但是,当我有不止一种类型的元素时,问题似乎就出现了。

例如:

文件1.xml

<?xml-stylesheet type="text/xsl" href="merge2.xsl"?>

<Main>
    <Records>
        <Record>
            <Description>A</Description>
        </Record>
        <Record>
            <Description>A</Description>
        </Record>
        <Record>
            <Description>B</Description>
        </Record>
        <Record>
            <Description>C</Description>
        </Record>
    </Records>
</Main>

merge2.xsl

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
    <table border="1">
        <tr>
            <th>Type</th>
            <th>Count</th>
        </tr>
        <xsl:for-each select="Main/Records/Record">
            <xsl:if test ="not(preceding-sibling::Record(Description/text() = current()/Description/text()])">
                <tr>
                    <td><xsl:value-of select="Description"/></td>
                    <td><xsl:value-of select="count(//Record[Description/text()=current()/Description/text()])"/></td>
                </tr>
            </xsl:if>
        </xsl:for-each>
    </table>
</xsl:template>
</xsl:stylesheet>

这很好用,给了我想要的结果。

Type    Count
 A        2
 B        1
 C        1

但是,如果我要添加另一个 Records 元素,它似乎会一个接一个地处理这两个元素,例如

<?xml-stylesheet type="text/xsl" href="merge2.xsl"?>

<Main>
    <Records>
        <Record>
            <Description>A</Description>
        </Record>
        <Record>
            <Description>A</Description>
        </Record>
        <Record>
            <Description>B</Description>
        </Record>
        <Record>
            <Description>C</Description>
        </Record>
    </Records>
    <Records>
        <Record>
            <Description>B</Description>
        </Record>
        <Record>
            <Description>A</Description>
        </Record>
        <Record>
            <Description>C</Description>
        </Record>
        <Record>
            <Description>C</Description>
        </Record>
    </Records>
</Main>

这将产生以下结果。

Type        Count
 A            3
 B            2
 C            3
 B            2
 A            3
 C            3

它似乎处理记录的第一个实例,然后转到下一个。有什么方法可以消除两者之间的重复项吗?

我已经尝试更改 for-each 以遍历记录的每个实例,并尝试为其创建一个单独的模板,但是我似乎仍然遗漏了一些东西,因为我没有设法让它工作。

非常感谢您的帮助。

最佳答案

尝试在 xsl:if 语句中将 preceding-sibling 替换为 preceding

您设计测试的想法是正确的,这样您每次遇到 Description 值时只发出一次 tr。但是,preceding-sibling 停止通过父级的直接子级进行回溯; preceding 继续检查文档中较早的部分,这是您要避免在 Records 中重复的内容。

仅供引用,还有一个拼写错误,其中 Record( 应该是 Record[。这是一个完整的操作转换,包括这些更改:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html"/>
  <xsl:template match="/">
    <table border="1">
      <tr>
        <th>Type</th>
        <th>Count</th>
      </tr>
      <xsl:for-each select="Main/Records/Record">
        <xsl:if test ="not(preceding::Record[Description/text() = current()/Description/text()])">
          <tr>
            <td><xsl:value-of select="Description"/></td>
            <td><xsl:value-of select="count(//Record[Description/text()=current()/Description/text()])"/></td>
          </tr>
        </xsl:if>
      </xsl:for-each>
    </table>
  </xsl:template>
</xsl:stylesheet>

关于xml - XSLT 忽略重复元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18897691/

相关文章:

java - 使用 XPath 连接选定子节点的值

html - 使用服务器端 XML 解析器生成 HTML 内容

xmlstarlet递归地从多个文档中删除父元素

xml - 基于另一个属性值限制 XSD 属性值

android - *有什么*方法可以将 Android/drawable 图形链接到/assets?

xml - 根据属性值修改元素的值

xml - XPath 如何处理 XML namespace ?

java - XSLT 性能注意事项

java - 输入 XML 中的中文字符导致 XSLT 转换在输出 XML 中产生无效字符引用

html - 使用 xpath 从 HTML 文件中提取 &lt;title&gt; 的最安全方法是什么?