I have the following structure to XML file:
<INSTANCE>
<Sections>
<Section>
<Forms>
<Form>
<Control id="GroupHeading1">
<Property/>
<Property/>
</Control>
<Control id="GroupHeading2">
<Property/>
<Control id="TextBox">
<Property/>
<Property/>
</Control>
</Control>
</Form>
</Forms>
</Section>
</Sections>
</INSTANCE>
I am trying to deserialize this into C# object, but I don't need to preserve the hierarchy (which is making it difficult for me to deserialize).
Is there XSL that can transform this to un-nest the Controls, and if possible add an attribute to any child Control with ParentId=""?
Thank you for any guidance!
Given XML, the XmlSerializer can produce a graph of objects that hold the same instance data.
This is known as XML de-serialization
You need to look here :
Using the XmlSerializer Attributes
Serialization and Deserialization in ASP.NET with C#
This template should get you started. I ran it against .NET 2.0.
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml"/>
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:apply-templates select="#*"/>
<xsl:apply-templates select="*"/>
</xsl:element>
</xsl:template>
<xsl:template match="Form">
<Form>
<xsl:copy-of select="#*"/>
<xsl:apply-templates select="//Control"/>
</Form>
</xsl:template>
<xsl:template match="Control">
<Control>
<xsl:if test="ancestor::Control/#id">
<xsl:attribute name="ParentID"><xsl:value-of select="ancestor::Control/#id"/></xsl:attribute>
</xsl:if>
<xsl:copy-of select="*|#*"/>
</Control>
</xsl:template>
</xsl:stylesheet>
This is the output (indented for readability).
<INSTANCE>
<Sections>
<Section>
<Forms>
<Form>
<Control id="GroupHeading1">
<Property />
<Property />
</Control>
<Control id="GroupHeading2">
<Property />
<Control id="TextBox">
<Property />
<Property />
</Control>
</Control>
<Control ParentID="GroupHeading2" id="TextBox">
<Property />
<Property />
</Control>
</Form>
</Forms>
</Section>
</Sections>
</INSTANCE>
The following stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
<!-- first-level control elements -->
<xsl:template match="Control">
<Control>
<xsl:copy-of select="#*|*[not(self::Control)]" />
</Control>
<xsl:apply-templates select="Control" />
</xsl:template>
<!-- nested control elements -->
<xsl:template match="Control/Control">
<Control ParentId="{../#id}">
<xsl:copy-of select="#*|*[not(self::Control)]" />
</Control>
<xsl:apply-templates select="Control" />
</xsl:template>
</xsl:stylesheet>
Applied to the following document (same as original with one additional level of nesting for demonstration purposes):
<INSTANCE>
<Sections>
<Section>
<Forms>
<Form>
<Control id="GroupHeading1">
<Property />
<Property />
</Control>
<Control id="GroupHeading2">
<Property />
<Control id="TextBox">
<Property />
<Property />
<Control id="Grandchild">
<Property />
</Control>
</Control>
</Control>
</Form>
</Forms>
</Section>
</Sections>
</INSTANCE>
Produces an output with no nested <Control> elements:
<INSTANCE>
<Sections>
<Section>
<Forms>
<Form>
<Control id="GroupHeading1">
<Property />
<Property />
</Control>
<Control id="GroupHeading2">
<Property />
</Control>
<Control ParentId="GroupHeading2" id="TextBox">
<Property />
<Property />
</Control>
<Control ParentId="TextBox" id="Grandchild">
<Property />
</Control>
</Form>
</Forms>
</Section>
</Sections>
</INSTANCE>
Related
I keep getting the error "Error 4: Could not load file or assembly 'MySql.Data.EntityFramework, Version=8.0.25.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)" when trying to compile my csproj. Any help would be greatly appreciated
here is my ucsdb.edmx
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="3.0" xmlns:edmx="http://schemas.microsoft.com/ado/2009/11/edmx">
<!-- EF Runtime content -->
<edmx:Runtime>
<!-- SSDL content -->
<edmx:StorageModels>
<Schema Namespace="ucsdbModel.Store" Provider="MySql.Data.MySqlClient"
ProviderManifestToken="5.6" Alias="Self"
xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator"
xmlns="http://schemas.microsoft.com/ado/2009/11/edm/ssdl">
<EntityType Name="Clan">
<Key>
<PropertyRef Name="ClanId" />
</Key>
<Property Name="ClanId" Type="bigint" Nullable="false" />
<Property Name="LastUpdateTime" Type="datetime" Precision="0" Nullable="false" />
<Property Name="Data" Type="text" Nullable="false" />
</EntityType>
<EntityType Name="Player">
<Key>
<PropertyRef Name="PlayerId" />
</Key>
<Property Name="PlayerId" Type="bigint" Nullable="false" />
<Property Name="Avatar" Type="text" Nullable="false" />
<Property Name="GameObjects" Type="text" Nullable="false" />
</EntityType>
<EntityContainer Name="ucsdbModelStoreContainer">
<EntitySet Name="Clan" EntityType="Self.Clan" Schema="ucsdb" store:Type="Tables" />
<EntitySet Name="Player" EntityType="Self.Player" Schema="ucsdb" store:Type="Tables" />
</EntityContainer>
</Schema>
</edmx:StorageModels>
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema Namespace="ucsdbModel" Alias="Self" annotation:UseStrongSpatialTypes="false"
xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation"
xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
<EntityType Name="Clan">
<Key>
<PropertyRef Name="ClanId" />
</Key>
<Property Name="ClanId" Type="Int64" Nullable="false" />
<Property Name="LastUpdateTime" Type="DateTime" Nullable="false" />
<Property Name="Data" Type="String" Nullable="false" MaxLength="65535"
FixedLength="false" Unicode="false" />
</EntityType>
<EntityType Name="Player">
<Key>
<PropertyRef Name="PlayerId" />
</Key>
<Property Name="PlayerId" Type="Int64" Nullable="false" />
<Property Name="Avatar" Type="String" Nullable="false" MaxLength="65535"
FixedLength="false" Unicode="false" />
<Property Name="GameObjects" Type="String" Nullable="false" MaxLength="65535"
FixedLength="false"
Unicode="false" />
</EntityType>
<EntityContainer Name="ucsdbEntities" annotation:LazyLoadingEnabled="true">
<EntitySet Name="Clan" EntityType="Self.Clan" />
<EntitySet Name="Player" EntityType="Self.Player" />
</EntityContainer>
</Schema>
</edmx:ConceptualModels>
<!-- C-S mapping content -->
<edmx:Mappings>
<Mapping Space="C-S"
xmlns="http://schemas.microsoft.com/ado/2009/11/mapping/cs
">
<EntityContainerMapping
StorageEntityContainer="ucsdbModelStoreContainer"
CdmEntityContainer="ucsdbEntities">
<EntitySetMapping Name="Clan">
<EntityTypeMapping TypeName="ucsdbModel.Clan">
<MappingFragment StoreEntitySet="Clan">
<ScalarProperty Name="ClanId"
ColumnName="ClanId" />
<ScalarProperty Name="LastUpdateTime"
ColumnName="LastUpdateTime" />
<ScalarProperty Name="Data"
ColumnName="Data" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
<EntitySetMapping Name="Player">
<EntityTypeMapping
TypeName="ucsdbModel.Player">
<MappingFragment StoreEntitySet="Player">
<ScalarProperty Name="PlayerId"
ColumnName="PlayerId" />
<ScalarProperty Name="GameObjects"
ColumnName="GameObjects" />
<ScalarProperty Name="Avatar"
ColumnName="Avatar" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
</EntityContainerMapping>
</Mapping>
</edmx:Mappings>
</edmx:Runtime>
<!-- EF Designer content (DO NOT EDIT MANUALLY BELOW
HERE) -->
<Designer
xmlns="http://schemas.microsoft.com/ado/2009/11/edmx">
<Connection>
<DesignerInfoPropertySet>
<DesignerProperty
Name="MetadataArtifactProcessing"
Value="EmbedInOutputAssembly" />
</DesignerInfoPropertySet>
</Connection>
<Options>
<DesignerInfoPropertySet>
<DesignerProperty Name="ValidateOnBuild"
Value="true" />
<DesignerProperty Name="EnablePluralization"
Value="false" />
<DesignerProperty Name="IncludeForeignKeysInModel"
Value="false" />
<DesignerProperty Name="UseLegacyProvider"
Value="false" />
<DesignerProperty Name="CodeGenerationStrategy"
Value="None" />
</DesignerInfoPropertySet>
</Options>
<!-- Diagram content (shape and connector positions) -
->
<Diagrams></Diagrams>
</Designer>
</edmx:Edmx>
Need to use MySql.Data.EntityFramework.8.0.25, but the program does not have this dll file or use another version.
Click on the project's directory, right-click References and open Manage NuGet Packages.
Search for MySql.Data.EntityFramework to see Version. I hope I can help you.
I'm new to XSLT and am having some problems trying to format an XML document which has recursive nodes.
There have 2 styles of tree node which are group and data.
The problem is my current XSLT template unable to generate the content when the Nodes have mixed of group and data styles.
XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:template match="Nodes[TreeNode]">
<xsl:apply-templates select="TreeNode" />
</xsl:template>
<xsl:template match="Nodes[not(TreeNode)]" />
<xsl:template match="TreeNode[Style='Data']">
<!--<table>
<thead>
<tr>
<th scope="col">Value</th>
</tr>
</thead>
<tbody>-->
<tr>
<td>
<xsl:value-of select="Value"/>
</td>
</tr>
<!--</tbody>
</table>-->
</xsl:template>
<xsl:template match="TreeNode[Style='Group']">
<group>
<p>
<xsl:value-of select="Label"/>
</p>
<xsl:apply-templates select="Nodes" />
</group>
</xsl:template>
</xsl:stylesheet>
XML
<?xml version="1.0" encoding="utf-8"?>
<TreeNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Label>Root</Label>
<Style>Group</Style>
<Nodes>
<TreeNode>
<Label>A</Label>
<Style>Group</Style>
<Nodes>
<TreeNode>
<Label>B</Label>
<Style>Group</Style>
<Nodes>
<TreeNode>
<Label />
<Value>AAA</Value>
<Style>Data</Style>
<Nodes />
</TreeNode>
<TreeNode>
<Label />
<Value>BBB</Value>
<Style>Data</Style>
<Nodes />
</TreeNode>
</Nodes>
</TreeNode>
<TreeNode>
<Label>C</Label>
<Style>Group</Style>
<Nodes>
<TreeNode>
<Label />
<Value>CCC</Value>
<Style>Data</Style>
<Nodes />
</TreeNode>
<TreeNode>
<Label />
<Value>DDD</Value>
<Style>Data</Style>
<Nodes />
</TreeNode>
</Nodes>
</TreeNode>
<TreeNode>
<Label>D</Label>
<Style>Group</Style>
<Nodes>
<TreeNode>
<Label />
<Value>EEE</Value>
<Style>Data</Style>
<Nodes />
</TreeNode>
</Nodes>
</TreeNode>
</Nodes>
</TreeNode>
</Nodes>
</TreeNode>
Expected Result:
You have two templates at the start of your XSLT
<xsl:template match="Nodes[TreeNode]">
<xsl:apply-templates select="TreeNode" />
</xsl:template>
<xsl:template match="Nodes[not(TreeNode)]" />
These could actually be merged into one; like so:
<xsl:template match="Nodes">
<xsl:apply-templates select="TreeNode" />
</xsl:template>
The reason being is that if Nodes does not have a TreeNode under it, then <xsl:apply-templates select="TreeNode" /> will not select anything anyway, so the effect is the same. (In fact, you could drop this template entirely if Nodes could only ever have TreeNode under it, as XSLT's built-in templates will do the same thing).
However, in answer to your problem, is that what I think you need is another template that you need another template that matches Nodes in the case where there is a child TreeNode for "Data"
<xsl:template match="Nodes[TreeNode/Style='Data']">
<table>
<xsl:apply-templates select="TreeNode" />
</table>
</xsl:template>
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:template match="Nodes[TreeNode/Style='Data']">
<table>
<xsl:apply-templates select="TreeNode" />
</table>
</xsl:template>
<xsl:template match="Nodes">
<xsl:apply-templates select="TreeNode" />
</xsl:template>
<xsl:template match="TreeNode[Style='Data']">
<tr>
<td>
<xsl:value-of select="Value"/>
</td>
</tr>
</xsl:template>
<xsl:template match="TreeNode[Style='Group']">
<group>
<p>
<xsl:value-of select="Label"/>
</p>
<xsl:apply-templates select="Nodes" />
</group>
</xsl:template>
</xsl:stylesheet>
I have the following xsl stylesheet and xml but I can't get the elements in the xml parent node in xsl template match is not working, I can't get table and costumer nodes from xml
<?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="/">
<HTML>
<HEAD>
<TITLE>Title</TITLE>
</HEAD>
<BODY>
<xsl:apply-templates/>
</BODY>
</HTML>
</xsl:template>
<xsl:template match="/parent">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="costumer">
<p>Costumer</p>
</xsl:template>
<xsl:template match="table">
<xsl:variable name="name" select="#name"/>
<xsl:variable name="type" select="#type"/>
<xsl:variable name="height" select="#height"/>
<xsl:variable name="width" select="#wdth"/>
<xsl:variable name="margin-top" select="#margin-top"/>
<xsl:variable name="margin-left" select="#margin-left"/>
<table id="{$name}" width="{$width}" height="{$height}" style="margin-top:{$margin-top}; margin-left:{$margin-left}">
<thead>
<tr>
<xsl:apply-templates select="*[1]/*" mode="th"/>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="*"/>
</tbody>
</table>
</xsl:template>
<xsl:template match="/*/*/*" mode="th">
<th>
<xsl:value-of select="*"/>
</th>
</xsl:template>
<xsl:template match="/*/*">
<tr>
<xsl:apply-templates select="*"/>
</tr>
</xsl:template>
<xsl:template match="/*/*/*">
<xsl:variable name="texttd" select="#text"/>
<td>
<xsl:value-of select="$texttd"/>
</td>
</xsl:template>
</xsl:stylesheet>
And below is xml file
<?xml version="1.0" encoding="utf-8"?>
<parent>
<table name="region1" type="td" wdth="0" height="0" margin-top="1" margin-left="122">
<td margin-top="0" margin-left="152" width="36" height="13" font-family="Arial-BoldMT" font-size="16" font-weight="0" text="??"?" line-height="300" is-visible="True" color="#0A4462" />
<Text name="region1" type="Title" wdth="0" height="0" margin-top="7" margin-left="138">
<Title margin-top="0" margin-left="14" width="36" height="13" font-family="Arial-BoldMT" font-size="16" font-weight="0" text="??"?" line-height="300" is-visible="True" color="#0A4462" />
</Text>
</table>
<table name="region1" type="td" wdth="0" height="0" margin-top="1" margin-left="122">
<td margin-top="0" margin-left="152" width="36" height="13" font-family="Arial-BoldMT" font-size="16" font-weight="0" text="??"?" line-height="300" is-visible="True" color="#0A4462" />
<Text name="region1" type="Title" wdth="0" height="0" margin-top="7" margin-left="138">
<Title margin-top="0" margin-left="14" width="36" height="13" font-family="Arial-BoldMT" font-size="16" font-weight="0" text="??"?" line-height="300" is-visible="True" color="#0A4462" />
</Text>
</table>
<table name="region1" type="td" wdth="0" height="0" margin-top="1" margin-left="122">
<td margin-top="0" margin-left="152" width="36" height="13" font-family="Arial-BoldMT" font-size="16" font-weight="0" text="??"?" line-height="300" is-visible="True" color="#0A4462" />
<Text name="region1" type="Title" wdth="0" height="0" margin-top="7" margin-left="138">
<Title margin-top="0" margin-left="14" width="36" height="13" font-family="Arial-BoldMT" font-size="16" font-weight="0" text="??"?" line-height="300" is-visible="True" color="#0A4462" />
</Text>
</table>
<costumer></costumer>
<costumer></costumer>
</parent>
The generic templates like <xsl:template match="/*/*/*" > get a higher priority. It seems the number of slashes / in an expression count towards the priority.
I think you should increase the priority of the templates you want by making the XPath more specific
<xsl:template match="/parent/table">
<xsl:template match="/parent/costumer">
This will still not work for the costumer, so you need to move it to the end of the stylesheet, because items at the end are preferred in case of equal priorities.
You could also reduce the priority on the generic items explicitly like this:
<xsl:template match="/*/*/*" priority="-1">
As an alternative you can increase the priority of the items you want explicitly:
<xsl:template match="table" priority="5">
Other that that I would need the full expected output to see if that all helps building the solution you're looking for.
BTW: I guess you want customer instead of costumer.
Added a Database and an Entity Model to my DAL Project.
got an error :
Error :
+ base {"Schema specified is not valid. Errors: \r\nMultiple types with the name 'TblRecord' exist in the EdmItemCollection in different namespaces. Convention based mapping requires unique names without regard to namespace in the EdmItemCollection."} System.Data.EntityException {System.Data.MetadataException}
The Edmx File
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="3.0" xmlns:edmx="http://schemas.microsoft.com/ado/2009/11/edmx">
<!-- EF Runtime content -->
<edmx:Runtime>
<!-- SSDL content -->
<edmx:StorageModels>
<Schema Namespace="Xz.Business.Matches.Store" Alias="Self" Provider="System.Data.SqlServerCe.4.0" ProviderManifestToken="4.0" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/11/edm/ssdl">
<EntityContainer Name="XzBusinessMatchesStoreContainer">
<EntitySet Name="Records" EntityType="Xz.Business.Matches.Store.Records" store:Type="Tables" />
</EntityContainer>
<EntityType Name="Records">
<Key>
<PropertyRef Name="Record" />
</Key>
<Property Name="Record" Type="nvarchar" Nullable="false" MaxLength="100" />
<Property Name="Relations" Type="nvarchar" MaxLength="450" />
</EntityType>
</Schema>
</edmx:StorageModels>
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema Namespace="Xz.Business.Matches" Alias="Self" p1:UseStrongSpatialTypes="false" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns:p1="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
<EntityContainer Name="RecordzEntities" p1:LazyLoadingEnabled="true">
<EntitySet Name="Records" EntityType="Xz.Business.Matches.TblRecord" />
</EntityContainer>
<EntityType Name="TblRecord">
<Key>
<PropertyRef Name="Record" />
</Key>
<Property Name="Record" Type="String" Nullable="false" MaxLength="100" Unicode="true" FixedLength="false" />
<Property Name="Relations" Type="String" MaxLength="450" Unicode="true" FixedLength="false" />
</EntityType>
</Schema>
</edmx:ConceptualModels>
<!-- C-S mapping content -->
<edmx:Mappings>
<Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2009/11/mapping/cs">
<EntityContainerMapping StorageEntityContainer="XzBusinessMatchesStoreContainer" CdmEntityContainer="RecordzEntities">
<EntitySetMapping Name="Records">
<EntityTypeMapping TypeName="Xz.Business.Matches.TblRecord">
<MappingFragment StoreEntitySet="Records">
<ScalarProperty Name="Record" ColumnName="Record" />
<ScalarProperty Name="Relations" ColumnName="Relations" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
</EntityContainerMapping>
</Mapping>
</edmx:Mappings>
</edmx:Runtime>
<!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->
<Designer xmlns="http://schemas.microsoft.com/ado/2009/11/edmx">
<Connection>
<DesignerInfoPropertySet>
<DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly" />
</DesignerInfoPropertySet>
</Connection>
<Options>
<DesignerInfoPropertySet>
<DesignerProperty Name="ValidateOnBuild" Value="true" />
<DesignerProperty Name="EnablePluralization" Value="True" />
<DesignerProperty Name="IncludeForeignKeysInModel" Value="True" />
<DesignerProperty Name="CodeGenerationStrategy" Value="None" />
</DesignerInfoPropertySet>
</Options>
<!-- Diagram content (shape and connector positions) -->
<Diagrams></Diagrams>
</Designer>
</edmx:Edmx>
Names & Namespaces :
Project Name : Business.Matches
Default Namespace : Xz.Business.Matches
I added an Entity Model with this definitions :
Model : RecordzModel
Context : RecordzContext
Model Namespace : Xz.Business.Matches
You seem to have more than one class in your project that is called 'TblRecord'. Namespaces are ignored when matching your types to EDM types for POCO types and therefore if you have more than one class with the same name it is ambiguous and causes the exception.
I have an xml content and i am applying xslt 1.0 for transformation on it. I am also passing parameters for filteration. but i am not able to to grouping on filtered data in xslt 1.0.
I will pass "Country Value" (as like 'United States') as parameter for filteration. after filteration, Grouping will be applied on "Group" field for filtered data. and if only one group exist then dont group data. grouping applied only in case if more then one group becomes possible.
please help me on this.
thanks in advance.
Here is my sample XML content.
<?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>
If you really wanted to do filtering first, then grouping, then you are looking at some sort of 'two pass' transform. This can be achieved by use of the node-set extension function, to create a result-tree fragment which contains the filtered data.
In the following example, I am using Microsoft's extension function, but depending on your platform, you may have to specify another. ( EXSLT is another common one. Use name space http://exslt.org/common for that. )
<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>
When this is used, the output should be as follows
<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>
See Understanding the node-set function for more information.
Unless you did a two-phase transform, I think you should probably do the grouping first, and then the filtering.
Grouping would be achieved by the common Meunchain Grouping method. You first define a key to look up DataRow elements based on their Group
<xsl:key name="RowLookup" match="DataRow" use="Group"/>
And then, to get the unique group names, you match the DataRow elements which happen to be the first occuring element in your key for their particular group
<xsl:apply-templates select="DataRow[generate-id() = generate-id(key('RowLookup', Group)[1])]"/>
So, now you have grouped by the Group elements, so you need to check there it at least one DataRow element for the current group that matches the filter
<xsl:if test="../DataRow[Group=current()/Group]/Country[Conty=$Conty]">
And then to get all DataRow elements for the current group, you could use the key
<xsl:apply-templates select="key('RowLookup', Group)" mode="ingroup"/>
Here is the full 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>
When you apply this XSLT to your sample XML, you get the following results
<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>
I am not sure if this is the exact structure you want, but I hope it gives you the general idea.