xml - 在 XSLT/XPath 中选择唯一记录

标签 xml xpath transform xslt

<xsl:for-each> 的上下文中,我必须从 XML 文档中仅选择唯一记录环形。我受 Visual Studio 限制只能使用 XSL 1.0

    <availList>
        <item>
          <schDate>2010-06-24</schDate>              
          <schFrmTime>10:00:00</schFrmTime>
          <schToTime>13:00:00</schToTime>
          <variousOtherElements></variousOtherElements>
        </item>
        <item>
          <schDate>2010-06-24</schDate>              
          <schFrmTime>10:00:00</schFrmTime>
          <schToTime>13:00:00</schToTime>
          <variousOtherElements></variousOtherElements>
        </item>
        <item>
          <schDate>2010-06-25</schDate>              
          <schFrmTime>10:00:00</schFrmTime>
          <schToTime>12:00:00</schToTime>
          <variousOtherElements></variousOtherElements>
        </item>
        <item>
          <schDate>2010-06-26</schDate>              
          <schFrmTime>13:00:00</schFrmTime>
          <schToTime>14:00:00</schToTime>
          <variousOtherElements></variousOtherElements>
        </item>
        <item>
          <schDate>2010-06-26</schDate>              
          <schFrmTime>10:00:00</schFrmTime>
          <schToTime>12:00:00</schToTime>
          <variousOtherElements></variousOtherElements>
        </item>
    </availList>

唯一性必须基于三个子元素的值:schDate , schFrmTimeschToTime .如果两个item元素的所有三个子元素都具有相同的值,它们是重复的。在上面的 XML 中,第一项和第二项是重复项。其余的都是独一无二的。如上所述,每个项目都包含我们不希望包含在比较中的其他元素。 “独特性”应该是这三个要素的一个因素,并且是单独的一个因素。

我试图通过以下方式实现这一目标:

availList/item[not(schDate = preceding:: schDate and schFrmTime = preceding:: schFrmTime and schToTime = preceding:: schToTime)]

这背后的想法是选择没有前面元素具有相同 schDate 的记录, schFrmTimeschToTime .但是,它的输出缺少最后一项。这是因为我的 XPath 实际上排除了在整个前面的文档中匹配所有子元素值 的项目。无单item匹配最后一个项目的所有子元素 - 但因为每个元素的值都单独存在于另一个项目中,所以最后一个项目被排除在外。

通过将所有子值作为串联字符串前面每个项目的相同串联值进行比较,我可以获得正确的结果。有人知道我可以做到这一点的方法吗?

最佳答案

我。作为单个 XPath 表达式:

/*/item[normalize-space() and not(. = preceding-sibling::item)]

二。更高效的 (XSLT) 实现,使用键:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kItemByVal" match="item" use="."/>

 <xsl:template match="/">
  <xsl:copy-of select=
   "*/item[generate-id() = generate-id(key('kItemByVal', .))]
   "/>
 </xsl:template>
</xsl:stylesheet>

I 和 II,当应用于提供的 XML 文档时,正确选择/复制以下节点:

<item><schDate>2010-06-24</schDate><schFrmTime>10:00:00</schFrmTime><schToTime>13:00:00</schToTime></item>
<item><schDate>2010-06-25</schDate><schFrmTime>10:00:00</schFrmTime><schToTime>12:00:00</schToTime></item>
<item><schDate>2010-06-26</schDate><schFrmTime>13:00:00</schFrmTime><schToTime>14:00:00</schToTime></item>
<item><schDate>2010-06-26</schDate><schFrmTime>10:00:00</schFrmTime><schToTime>12:00:00</schToTime></item>

更新:以防<item>有其他 child ,那么这个变换:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:key name="kItemBy3Children" match="item"
     use="concat(schDate, '+', schFrmTime, '+', schToTime)"/>

 <xsl:template match="/">
       <xsl:copy-of select=
        "*/item[generate-id()
              = generate-id(key('kItemBy3Children',
                                concat(schDate,
                                       '+', schFrmTime,
                                       '+', schToTime)
                               )
                            )
               ]
        "/>
 </xsl:template>
</xsl:stylesheet>

产生想要的结果

关于xml - 在 XSLT/XPath 中选择唯一记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3016929/

相关文章:

vector - 如何将 3D 空间坐标转换为 2D 空间坐标?

c# - 具有多个 XML 输入文件的 XSLT 转换

function - WSO2 ESB 4.8.1 中支持的 XPath 函数

PHP XPath 检查是否为空

c - 霍夫变换: improving algorithm efficiency over OpenCL

html - 将旋转文本锚定到父元素的上限

python - 从 MediaWiki 的 API 维基文本中提取 Python 中的模板参数

javascript - xml 数据未显示在 html 页面中

javascript - 多个字符串的单个 XPath?

java - 重写 XML 文件时使用哪种 Java XML 解析方法?