C# xslt中xml数据的过滤和分组

C# xslt中xml数据的过滤和分组,c#,xml,xslt,C#,Xml,Xslt,我有一个xml内容,我正在应用XSLT1.0进行转换。我还传递过滤参数。但我无法在XSLT1.0中对过滤后的数据进行分组 我将传递“国家值”(如“美国”)作为过滤参数。过滤后,分组将应用于过滤数据的“组”字段。如果只存在一个组,则不要对数据进行分组。仅当可能有多个组时才应用分组 请帮我做这个 提前谢谢 下面是我的示例XML内容 <?xml version="1.0" encoding="utf-8" ?> <DataRows> -<DataRow>

我有一个xml内容,我正在应用XSLT1.0进行转换。我还传递过滤参数。但我无法在XSLT1.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>

-
- 
美国
大不列颠联合王国
第一组
1.
姓名1_1
标题1
732-989-9898
-
- 
美国
大不列颠联合王国
第一组
2.
名称2_2
标题2
732-989-9898
-
- 
美国
第一组
1.
姓名3_1
标题3
732-989-9898
-
- 
美国
德国
第一组
2.
名称4_2
标题4
732-989-9898
-
- 
美国
第2组
4.
姓名8_4
标题8
732-989-9898
-
- 
大不列颠联合王国
第2组
1.
姓名9_1
标题9
732-989-9898
-
- 
美国
德国
第2组
3.
姓名5_3
标题5
732-989-9898
-
- 
美国
德国
第2组
4.
姓名6_4
标题6
732-989-9898
-
- 
美国
第2组
3.
姓名7_3
标题7
732-989-9898
-
- 
德国
第一组
1.
姓名10_1
标题10
732-989-9898

除非您进行了两阶段转换,否则我认为您可能应该首先进行分组,然后进行过滤

分组将通过通用的Meunchain分组方法实现。首先定义一个键,以便根据组查找数据行元素

<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.
姓名1_1
标题1
732-989-9898
2.
名称2_2
标题2
732-989-9898
1.
姓名9_1
标题9
732-989-9898

我不确定这是否是您想要的确切结构,但我希望它能为您提供总体思路。

如果您真的想先进行过滤,然后进行分组,那么您将看到某种“两次”转换。这可以通过使用节点集扩展函数来实现,以创建包含过滤数据的结果树片段

在下面的示例中,我正在使用Microsoft的扩展功能,但根据您的平台,您可能需要指定另一个扩展功能。(EXSLT是另一种常见的方法。请使用名称空间。)


大不列颠联合王国
使用此选项时,输出应如下所示

<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.
姓名1_1
标题1
732-989-9898
2.
名称2_2
标题2
732-989-9898
1.
姓名9_1
标题9
732-989-9898

有关更多信息,请参阅。

非常感谢Tim的回复,并花时间研究这个问题。很抱歉,您提供给我的xslt都不起作用。如果你能给我一些解决方案,先做过滤,然后分组,这将是伟大的,但如果不可能,你会给我的解决方案,将做分组,然后过滤,这也将是伟大的。这对我工作!当你尝试的时候,你能更精确地描述一下发生在你身上的事情吗?你有错误吗?输出XML是否不符合预期?如果你能提供一个你所期望的输出的例子,那会有很大帮助。对不起,蒂姆,这是我的错,你的xslt部分工作得很好。事实上,我还有一些其他的东西和你给我的东西,我在把你的xslt和我的xslt集成在一起时犯了一个小错误。但我会保持您的部分不变,并稍微调整一下xslt及其工作方式。但我还是试着先过滤,然后分组,如果只有一个组,就不要分组项目。若我通过了过滤器值,并基于它,若只有一个组是可能的,那个么就并没有了
<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>