Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml 仅从与属性值匹配的列表中选择第一个元素_Xml_Xslt_Xpath - Fatal编程技术网

Xml 仅从与属性值匹配的列表中选择第一个元素

Xml 仅从与属性值匹配的列表中选择第一个元素,xml,xslt,xpath,Xml,Xslt,Xpath,我希望能够从属性值匹配的集合中选择第一个XML元素。为了进一步解释,假设我们有以下XML: <events> <event date="2013-06-17"> <person first="Joe" last="Bloggs" /> <person first="John" last="Smith" /> </event> <event date="2013-01-29"&

我希望能够从属性值匹配的集合中选择第一个XML元素。为了进一步解释,假设我们有以下XML:

<events>
    <event date="2013-06-17">
        <person first="Joe" last="Bloggs" />
        <person first="John" last="Smith" />
    </event>
    <event date="2013-01-29">
        <person first="Jane" last="Smith" />
        <person first="John" last="Smith" />
    </event>
    <event date="2012-09-03">
        <person first="Joe" last="Bloggs" />
        <person first="John" last="Doe" />
    </event>
    <event date="2012-04-05">
        <person first="Jane" last="Smith" />
        <person first="John" last="Smith" />
        <person first="John" last="Doe" />
    </event>
<event>

当然,
current()
函数不会喜欢这样,但我只是想知道是否有人知道如何在单个XPath语句中实现这一点?

下面是一个XSLT 2.0方法,使用
对每个组使用
分组:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output indent="yes"/>

<xsl:template match="events">
  <xsl:for-each-group select="event/person" group-by="concat(@first, '|', @last)">
    <xsl:copy-of select="."/>
  </xsl:for-each-group>
</xsl:template>

</xsl:stylesheet>
使用XSLT2.0和
对每个组
都需要使用一个变量来存储项,例如

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output indent="yes"/>

<xsl:template match="events">
  <xsl:variable name="first-person-in-groups" as="element(person)*">
    <xsl:for-each-group select="event/person" group-by="concat(@first, '|', @last)">
      <xsl:copy-of select="."/>
    </xsl:for-each-group>
  </xsl:variable>
  <xsl:apply-templates select="$first-person-in-groups"/>
</xsl:template>

<xsl:template match="person">
  <foo>...</foo>
</xsl:template>

</xsl:stylesheet>

...

这样,您就有了一系列
person
元素,您可以
应用模板

这里是一个XSLT 2.0方法,使用
对每个组
分组依据

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output indent="yes"/>

<xsl:template match="events">
  <xsl:for-each-group select="event/person" group-by="concat(@first, '|', @last)">
    <xsl:copy-of select="."/>
  </xsl:for-each-group>
</xsl:template>

</xsl:stylesheet>
使用XSLT2.0和
对每个组
都需要使用一个变量来存储项,例如

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output indent="yes"/>

<xsl:template match="events">
  <xsl:variable name="first-person-in-groups" as="element(person)*">
    <xsl:for-each-group select="event/person" group-by="concat(@first, '|', @last)">
      <xsl:copy-of select="."/>
    </xsl:for-each-group>
  </xsl:variable>
  <xsl:apply-templates select="$first-person-in-groups"/>
</xsl:template>

<xsl:template match="person">
  <foo>...</foo>
</xsl:template>

</xsl:stylesheet>

...

这样,您就有了一系列
person
元素,可以
应用模板

您能够使用XSLT 2.0或XSTL 1.0吗?在XSLT2.0中,可以对每个组元素使用xsl:。在XSLT 1.0中,您将使用一种称为Muenchian分组的技术。我可以使用XSL 2.0,但是,尽管for each group比我目前所做的工作更简洁,但它没有解决以下问题:例如,如何将选择声明为可以使用的单个XPath语句,在应用模板调用中。您能够使用XSLT 2.0或XSTL 1.0吗?在XSLT2.0中,可以对每个组元素使用xsl:。在XSLT 1.0中,您将使用一种称为Muenchian分组的技术。我可以使用XSL 2.0,但是,尽管for each group比我目前所做的工作更简洁,但它没有解决以下问题:例如,如何将选择声明为可以使用的单个XPath语句,这个答案与我已经采用的解决方案具有相同的结构,尽管有点简洁,但没有解决我提出的实际问题:这可以作为单个XPath语句来实现吗?如果可以,如何实现?不过,我想从这里可以猜到,答案是这是不可能的。我的XSLT 1.0解决方案是对XSLT 2.0的重写(在这里,每个组都需要
),但我将向您展示如何在XSLT 1.0和2.0中定义键的情况下,使用单个表达式过滤掉每个组中的第一个表达式。@rumplestiltzkin,我对答案进行了编辑,以展示如何在节点集上分别按唯一的
个人
项目顺序应用模板。但是,它是XSLT和XPath的组合,而不是单个XPath表达式!我曾尝试过使用Muenchian分组方法,但我无法让它用于元素和属性,只能用于原子数据。很明显,我搜索得不够深入。这个答案与我已经采用的解决方案的结构相同,虽然有点简洁,但没有解决我提出的实际问题:这可以作为一个XPath语句来完成吗?如果可以,如何完成?不过,我想从这里可以猜到,答案是这是不可能的。我的XSLT 1.0解决方案是对XSLT 2.0的重写(在这里,每个组都需要
),但我将向您展示如何在XSLT 1.0和2.0中定义键的情况下,使用单个表达式过滤掉每个组中的第一个表达式。@rumplestiltzkin,我对答案进行了编辑,以展示如何在节点集上分别按唯一的
个人
项目顺序应用模板。但是,它是XSLT和XPath的组合,而不是单个XPath表达式!我曾尝试过使用Muenchian分组方法,但我无法让它用于元素和属性,只能用于原子数据。很明显,我找得不够远。
<events>
    <event date="2013-06-17">
        <person first="Joe" last="Bloggs" />
        <person first="John" last="Smith" />
    </event>
    <event date="2013-01-29">
        <person first="Jane" last="Smith" />
        <person first="John" last="Smith" />
    </event>
    <event date="2012-09-03">
        <person first="Joe" last="Bloggs" />
        <person first="John" last="Doe" />
    </event>
    <event date="2012-04-05">
        <person first="Jane" last="Smith" />
        <person first="John" last="Smith" />
        <person first="John" last="Doe" />
    </event>
</events>
<person first="Joe" last="Bloggs"/>
<person first="John" last="Smith"/>
<person first="Jane" last="Smith"/>
<person first="John" last="Doe"/>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output indent="yes"/>

<xsl:key name="by-name" match="event/person" use="concat(@first, '|', @last)"/>

<xsl:template match="events">
  <xsl:for-each select="event/person[generate-id() = generate-id(key('by-name', concat(@first, '|', @last))[1])]">
    <xsl:copy-of select="."/>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output indent="yes"/>

<xsl:key name="by-name" match="event/person" use="concat(@first, '|', @last)"/>

<xsl:template match="events">
  <xsl:copy-of select="event/person[generate-id() = generate-id(key('by-name', concat(@first, '|', @last))[1])]"/>
</xsl:template>

</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output indent="yes"/>

<xsl:key name="by-name" match="event/person" use="concat(@first, '|', @last)"/>

<xsl:template match="events">
  <xsl:apply-templates select="event/person[generate-id() = generate-id(key('by-name', concat(@first, '|', @last))[1])]"/>
</xsl:template>

<xsl:template match="person">
  <foo>...</foo>
</xsl:template>

</xsl:stylesheet>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output indent="yes"/>

<xsl:template match="events">
  <xsl:variable name="first-person-in-groups" as="element(person)*">
    <xsl:for-each-group select="event/person" group-by="concat(@first, '|', @last)">
      <xsl:copy-of select="."/>
    </xsl:for-each-group>
  </xsl:variable>
  <xsl:apply-templates select="$first-person-in-groups"/>
</xsl:template>

<xsl:template match="person">
  <foo>...</foo>
</xsl:template>

</xsl:stylesheet>