我有一个xml内容,我正在应用xslt 1.0进行转换。我也传递过滤参数。但我无法对xslt 1.0中的过滤数据进行分组。
我会将“国家价值”(与“美国”一样)作为过滤参数。过滤后,分组将应用于“组”字段以过滤数据。如果只存在一个组,则不要对数据进行分组。仅当多于一个组成为可能时才应用分组。
请帮助我。
提前感谢。
以下是我的示例XML内容。
<?xml version="1.0" encoding="utf-8" ?>
<DataRows>
-<DataRow>
- <Country>
<Conty>United States</Conty>
<Conty>United Kingdom</Conty>
</Country>
<Group>Group 1</Group>
<Order>1</Order>
<Name>Name 1_1</Name>
<Title>Title 1</Title>
<PhoneNo>732-989-9898</PhoneNo>
<ImageUrl />
<EmailId />
</DataRow>
-<DataRow>
- <Country>
<Conty>United States</Conty>
<Conty>United Kingdom</Conty>
</Country>
<Group>Group 1</Group>
<Order>2</Order>
<Name>Name 2_2</Name>
<Title>Title 2</Title>
<PhoneNo>732-989-9898</PhoneNo>
<ImageUrl />
<EmailId />
</DataRow>
-<DataRow>
- <Country>
<Conty>United States</Conty>
</Country>
<Group>Group 1</Group>
<Order>1</Order>
<Name>Name 3_1</Name>
<Title>Title 3</Title>
<PhoneNo>732-989-9898</PhoneNo>
<ImageUrl />
<EmailId />
</DataRow>
-<DataRow>
- <Country>
<Conty>United States</Conty>
<Conty>Germany</Conty>
</Country>
<Group>Group 1</Group>
<Order>2</Order>
<Name>Name 4_2</Name>
<Title>Title 4</Title>
<PhoneNo>732-989-9898</PhoneNo>
<ImageUrl />
<EmailId />
</DataRow>
-<DataRow>
- <Country>
<Conty>United States</Conty>
</Country>
<Group>Group 2</Group>
<Order>4</Order>
<Name>Name 8_4</Name>
<Title>Title 8</Title>
<PhoneNo>732-989-9898</PhoneNo>
<ImageUrl />
<EmailId />
</DataRow>
-<DataRow>
- <Country>
<Conty>United Kingdom</Conty>
</Country>
<Group>Group 2</Group>
<Order>1</Order>
<Name>Name 9_1</Name>
<Title>Title 9</Title>
<PhoneNo>732-989-9898</PhoneNo>
<ImageUrl />
<EmailId />
</DataRow>
-<DataRow>
- <Country>
<Conty>United States</Conty>
<Conty>Germany</Conty>
</Country>
<Group>Group 2</Group>
<Order>3</Order>
<Name>Name 5_3</Name>
<Title>Title 5</Title>
<PhoneNo>732-989-9898</PhoneNo>
<ImageUrl />
<EmailId />
</DataRow>
-<DataRow>
- <Country>
<Conty>United States</Conty>
<Conty>Germany</Conty>
</Country>
<Group>Group 2</Group>
<Order>4</Order>
<Name>Name 6_4</Name>
<Title>Title 6</Title>
<PhoneNo>732-989-9898</PhoneNo>
<ImageUrl />
<EmailId />
</DataRow>
-<DataRow>
- <Country>
<Conty>United States</Conty>
</Country>
<Group>Group 2</Group>
<Order>3</Order>
<Name>Name 7_3</Name>
<Title>Title 7</Title>
<PhoneNo>732-989-9898</PhoneNo>
<ImageUrl />
<EmailId />
</DataRow>
-<DataRow>
- <Country>
<Conty>Germany</Conty>
</Country>
<Group>Group 1</Group>
<Order>1</Order>
<Name>Name 10_1</Name>
<Title>Title 10</Title>
<PhoneNo>732-989-9898</PhoneNo>
<ImageUrl />
<EmailId />
</DataRow>
</DataRows>
答案 0 :(得分:0)
除非您进行了两阶段转换,否则我认为您应该首先进行分组,然后进行过滤。
通过共同的Meunchain分组方法实现分组。您首先要定义一个键,以便根据组
来查找 DataRow 元素<xsl:key name="RowLookup" match="DataRow" use="Group"/>
然后,要获取唯一的组名,请匹配DataRow元素,这些元素恰好是您的特定组中键中的第一个出现元素
<xsl:apply-templates select="DataRow[generate-id() = generate-id(key('RowLookup', Group)[1])]"/>
因此,现在您已按组元素进行分组,因此您需要检查当前组中与过滤器匹配的至少一个DataRow元素
<xsl:if test="../DataRow[Group=current()/Group]/Country[Conty=$Conty]">
然后要获取当前组的所有DataRow元素,您可以使用密钥
<xsl:apply-templates select="key('RowLookup', Group)" mode="ingroup"/>
这是完整的XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="Conty">United Kingdom</xsl:param>
<xsl:key name="RowLookup" match="DataRow" use="Group"/>
<xsl:template match="/DataRows">
<xsl:copy>
<!-- Select unique groups -->
<xsl:apply-templates
select="DataRow[generate-id() = generate-id(key('RowLookup', Group)[1])]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="DataRow">
<!-- Check any DataRow elements for the current group match the filter -->
<xsl:if test="../DataRow[Group=current()/Group]/Country[Conty=$Conty]">
<Group>
<xsl:attribute name="name">
<xsl:value-of select="Group"/>
</xsl:attribute>
<!-- Get all the DataRow elements for the current group -->
<xsl:apply-templates select="key('RowLookup', Group)" mode="ingroup"/>
</Group>
</xsl:if>
</xsl:template>
<xsl:template match="DataRow" mode="ingroup">
<!-- Check this DataRow matches the filter -->
<xsl:if test="Country[Conty=$Conty]">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:if>
</xsl:template>
<!-- Ignore Group and Country elements -->
<xsl:template match="Group|Country"/>
<!-- Standard Identity Transform for all other nodes -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
将此XSLT应用于示例XML时,您将获得以下结果
<DataRows>
<Group name="Group 1">
<DataRow>
<Order>1</Order>
<Name>Name 1_1</Name>
<Title>Title 1</Title>
<PhoneNo>732-989-9898</PhoneNo>
<ImageUrl/>
<EmailId/>
</DataRow>
<DataRow>
<Order>2</Order>
<Name>Name 2_2</Name>
<Title>Title 2</Title>
<PhoneNo>732-989-9898</PhoneNo>
<ImageUrl/>
<EmailId/>
</DataRow>
</Group>
<Group name="Group 2">
<DataRow>
<Order>1</Order>
<Name>Name 9_1</Name>
<Title>Title 9</Title>
<PhoneNo>732-989-9898</PhoneNo>
<ImageUrl/>
<EmailId/>
</DataRow>
</Group>
</DataRows>
我不确定这是否是您想要的确切结构,但我希望它能为您提供一般性的想法。
答案 1 :(得分:0)
如果您真的想先进行过滤,然后进行分组,那么您正在寻找某种“双通”变换。这可以通过使用节点集扩展函数来实现,以创建包含过滤数据的结果树片段。
在下面的示例中,我使用的是Microsoft的扩展功能,但根据您的平台,您可能需要指定另一个。 (EXSLT是另一个常见的。使用名称空间http://exslt.org/common。)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="Conty">United Kingdom</xsl:param>
<xsl:variable name="FilteredData">
<xsl:apply-templates select="/DataRows/DataRow" mode="filter"/>
</xsl:variable>
<xsl:template match="DataRow" mode="filter">
<!-- Check this DataRow matches the filter -->
<xsl:if test="Country[Conty=$Conty]">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="filter"/>
</xsl:copy>
</xsl:if>
</xsl:template>
<!-- Ignore Country node in the filter -->
<xsl:template match="Country" mode="filter"/>
<!-- Identity template for filter -->
<xsl:template match="@*|node()" mode="filter">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="filter"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/DataRows">
<xsl:copy>
<!-- Read the filtered data -->
<xsl:choose>
<!-- Check there is a Group which differs from the first group -->
<xsl:when test="msxsl:node-set($FilteredData)/DataRow[position() > 1][Group != msxsl:node-set($FilteredData)/DataRow[1]/Group]">
<xsl:apply-templates select="msxsl:node-set($FilteredData)"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="msxsl:node-set($FilteredData)" mode="nogroup"/>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
<!-- Filtered data row -->
<xsl:template match="DataRow">
<!-- Is this DataRow the first in the group -->
<xsl:if test="not(preceding-sibling::DataRow[Group=current()/Group])"><!-- If so, create the group node -->
<Group>
<xsl:attribute name="name">
<xsl:value-of select="Group"/>
</xsl:attribute><!-- Get all the DataRow elements from the filter for the current group -->
<xsl:apply-templates select="../DataRow[Group=current()/Group]" mode="ingroup"/>
</Group>
</xsl:if>
</xsl:template>
<!-- Identity template for the group -->
<xsl:template match="@*|node()" mode="ingroup">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="ingroup"/>
</xsl:copy>
</xsl:template>
<!-- Ignore Group and Country node in the grouping -->
<xsl:template match="Group|Country" mode="ingroup"/>
<!-- Identity template for no grouping -->
<xsl:template match="@*|node()" mode="nogroup">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="nogroup"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
使用此选项时,输出应如下
<DataRows>
<Group name="Group 1">
<DataRow>
<Order>1</Order>
<Name>Name 1_1</Name>
<Title>Title 1</Title>
<PhoneNo>732-989-9898</PhoneNo>
<ImageUrl/>
<EmailId/>
</DataRow>
<DataRow>
<Order>2</Order>
<Name>Name 2_2</Name>
<Title>Title 2</Title>
<PhoneNo>732-989-9898</PhoneNo>
<ImageUrl/>
<EmailId/>
</DataRow>
</Group>
<Group name="Group 2">
<DataRow>
<Order>1</Order>
<Name>Name 9_1</Name>
<Title>Title 9</Title>
<PhoneNo>732-989-9898</PhoneNo>
<ImageUrl/>
<EmailId/>
</DataRow>
</Group>
</DataRows>
有关详细信息,请参阅Understanding the node-set function。