I am quite new to XML-XSLT coding.
I am binding XmlDataSource to my gridview by using XSLT. I want to sort the column upon clicking on the header. I do not want to convert xml to dataset and bind to gridview to achieve sorting. Here is my code:
<asp:XmlDataSource ID="XmlDataSource1" runat="server"></asp:XmlDataSource>
<asp:GridView ID="gvResult" runat="server" HorizontalAlign="Center" AutoGenerateColumns="false" HeaderStyle-BackColor="#3AC0F2" HeaderStyle-ForeColor="White" AllowPaging="True"
OnPageIndexChanging="gvResult_PageIndexChanging" AllowSorting="true" OnSorting="gvResult_Sorting">
<Columns>
<asp:TemplateField HeaderText="ID" SortExpression="ID">
<ItemTemplate>
<asp:HyperLink runat="server" NavigateUrl='~/NewForm.aspx?ID=<%# XPath("#ID") %>'>
<%# XPath("#ID") %>
</asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="employee_number" HeaderText="Employee Number" SortExpression="last_name"/>
<asp:BoundField DataField="name" HeaderText="Employee Name" SortExpression="last_name" />
<asp:BoundField DataField="date_joining" HeaderText="Joining Date" SortExpression="date_joining" />
<asp:BoundField DataField="date_paid" HeaderText="Date Paid" SortExpression="last_name"/>
<asp:BoundField DataField="amount" HeaderText="Salary" />
<asp:BoundField DataField="status" HeaderText="Status" />
</Columns>
</asp:GridView>
protected void gvResult_Sorting(object sender, GridViewSortEventArgs e)
{
XsltArgumentList xslTrnsform = new XsltArgumentList();
switch (e.SortExpression)
{
case "employee_number":
xslTrnsform.AddParam("sortby", "", "employee_number");
xslTrnsform.AddParam("order", "", "ascending");
//xslTrnsform.AddParam("datatype", "", "number");
break;
case "date_joining":
xslTrnsform.AddParam("sortby", "", "#date_joining");
xslTrnsform.AddParam("order", "", "ascending");
//xslTrnsform.AddParam("data-type", "", "text");
break;
case "date_paid":
xslTrnsform.AddParam("sortby", "", "#date_paid");
xslTrnsform.AddParam("order", "", "ascending");
//xslTrnsform.AddParam("data-type", "", "text");
break;
}
XmlDataSource1.EnableCaching = false;
XmlDataSource1.Data = ResponseObj.OuterXml;
XmlDataSource1.TransformArgumentList = xslTrnsform;
XmlDataSource1.TransformFile = "employees.xslt";
XmlDataSource1.XPath = "/employees/employee"; ;
// Bind the DataSet to the grid view
gvResult.DataSource = XmlDataSource1;
gvResult.DataBind();
gvResult.Visible = true;
}
<?xml version="1.0" encoding="utf-8" ?>
<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="sortby" select="#employee_number"/>
<xsl:param name="order" select="'ascending'"/>
<xsl:template match="employees">
<employees>
<xsl:apply-templates select="employee">
<xsl:sort select="*[name()=$sortby]" order="{$order}" />
</xsl:apply-templates>
</employees>
</xsl:template>
<xsl:template match="employee">
<employee>
<xsl:attribute name="ID">
<xsl:value-of select="#ID"/>
</xsl:attribute>
<xsl:attribute name="employee_number">
<xsl:value-of select="#employee_number"/>
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="#last_name"/>, <xsl:value-of select="#first_name"/>
</xsl:attribute>
<xsl:attribute name="date_joining">
<xsl:value-of select="#date_joining" />
</xsl:attribute>
<xsl:attribute name="dte_to_date">
<xsl:value-of select="#dte_to_date" />
</xsl:attribute>
<xsl:attribute name="date_paid">
<xsl:value-of select="#date_paid"/>
</xsl:attribute>
<xsl:attribute name="date_paid">
<xsl:value-of select="#date_paid"/>
</xsl:attribute>
<xsl:attribute name="amount">
<xsl:value-of select="#amount"/>
</xsl:attribute>
<xsl:attribute name="status">
<xsl:value-of select="#status"/>
</xsl:attribute>
</employee>
</xsl:template>
</xsl:stylesheet>
Data is displayed on the gridview. But when I click on header, nothing happens. Also I have to apply sorting for "name" column, which consists of lastname,firstname.
One problem you have is you are inconsistent about how you are setting the sortby parameters. In one place you do this...
xslTrnsform.AddParam("sortby", "", "employee_number");
But in another place you do this...
xslTrnsform.AddParam("sortby", "", "#date_joining");
As it looks like all your data is held in attributes, for the sake of consistency, it might be easier to drop the # prefix in all cases. Then, your xsl:sort can look like this
<xsl:sort select="#*[name()=$sortby]" order="{$order}" />
(Previously you were doing select="*[name()=$sortby] which would look for elements not attributes.)
To get your name column to sort by last_name and first_name you could add a second sorting parameter
case "name":
xslTrnsform.AddParam("sortby", "", "last_name");
xslTrnsform.AddParam("sortbysecond", "", "first_name");
xslTrnsform.AddParam("order", "", "ascending");
break;
Then, assuming you declare the sortbysecond parameter in your XSLT, your sort would look like this
<xsl:apply-templates select="employee">
<xsl:sort select="#*[name()=$sortby]" order="{$order}" />
<xsl:sort select="#*[name()=$sortbysecond]" order="{$order}" />
</xsl:apply-templates>
Try this XSLT...
<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="sortby" select="'employee_number'"/>
<xsl:param name="sortbysecond" select="'employee_number'"/>
<xsl:param name="order" select="'descending'"/>
<xsl:template match="employees">
<employees>
<xsl:apply-templates select="employee">
<xsl:sort select="#*[name()=$sortby]" order="{$order}" />
<xsl:sort select="#*[name()=$sortbysecond]" order="{$order}" />
</xsl:apply-templates>
</employees>
</xsl:template>
<xsl:template match="employee">
<employee ID="{#ID}"
employee_number="{#employee_number}"
name="{#last_name}, {#first_name}"
date_joining="{#data_joining}"
dte_to_date="{#dte_to_date}"
date_paid="{#date_paid}"
date_paid="{#date_paid}"
amount="{#amount}"
status="{#status}">
</employee>
</xsl:template>
</xsl:stylesheet>
Note the use of Attribute Value Templates, as Michael Kay mentioned in comments, which simplify your XSLT greatly.
Related
I have below node which needs to be added in xslt if not exists :-
<xsl:template name="URLSpliter">
<xsl:param name="url" />
<xsl:variable name="splitURL" select="substring-after($url, '/')" />
<xsl:if test="contains($splitURL, '/')">
<!--To call the template recursively-->
<xsl:call-template name="URLSpliter">
<xsl:with-param name="url" select="$splitURL" />
</xsl:call-template>
</xsl:if>
<xsl:if test="not(contains($splitURL, '/'))">
<xsl:value-of select="$splitURL" />
</xsl:if>
</xsl:template>
For this, first I need to check if it exists or not ?-
I have checked it through -
IEnumerable<XElement> xElements = from xmlAuthor in doc.Descendants()
let xElement = xmlAuthor.Element("URLSpliter")
where xElement != null
select xmlAuthor;
var IsUrlSplitterExists= xElements.Any();
if(IsUrlSplitterExists)
{
}
1.I want to know if its correct way or not?
If not exists (element [name="URLSpliter"]) then needs to add.
How can I add it as a first node of xslt?
To select such elements in the XSLT namespace with LINQ to XML you would use
XNamespace xsl = "http://www.w3.org/1999/XSL/Transform";
if (!doc.Root.Elements(xsl + "template").Where(t => (string)t.Attribute("name") == "URLSplitter").Any()) {
doc.Root.AddFirst(new XElement(xsl + "template", new XAttribute("name", "URLSplitter"), ...))
}
Of course, as XSLT is XML, you might as well use XSLT to manipulate your XSLT:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:axsl="http://www.w3.org/1999/XSL/Transform-alias"
exclude-result-prefixes="axsl"
version="1.0">
<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>
<xsl:output indent="yes"/>
<xsl:param name="new-template">
<axsl:template name="URLSpliter">
<axsl:param name="url" />
<axsl:variable name="splitURL" select="substring-after($url, '/')" />
<axsl:if test="contains($splitURL, '/')">
<!--To call the template recursively-->
<axsl:call-template name="URLSpliter">
<axsl:with-param name="url" select="$splitURL" />
</axsl:call-template>
</axsl:if>
<axsl:if test="not(contains($splitURL, '/'))">
<axsl:value-of select="$splitURL" />
</axsl:if>
</axsl:template>
</xsl:param>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="xsl:transform[not(xsl:template[#name = 'URLSplitter'])] | xsl:stylesheet[not(xsl:template[#name = 'URLSplitter'])]">
<xsl:copy>
<xsl:apply-templates select="#*"/>
<xsl:copy-of select="$new-template"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/94rmq5T
I want to merge nodes of two xml files in C# or XSLT. If the Path value of Method nodes of two different xml files are same. The two Method nodes should be merged as one in the output.
Example:
File1:
<Methods>
<Method>
<ID>1234</ID>
<Name>manager</Name>
<Path>path1</Path>
</Method>
</Methods>
File2:
<Methods>
<Method>
<Path>path1</Path>
<Description>text</Description>
</Method>
</Methods>
Output:
<Methods>
<Method>
<ID>1234</ID>
<Name>manager</Name>
<Description>text</Description>
</Method>
</Methods>
Try it this way?
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="file2" select="document('file2.xml')" />
<xsl:key name="method-by-path" match="Method" use="Path" />
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Method">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
<xsl:variable name="path" select="Path"/>
<!-- switch context to the other file -->
<xsl:for-each select="$file2">
<xsl:copy-of select="key('method-by-path', $path)/*[not(self::Path)]" />
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Note: this does not check for duplicate nodes.
LINQ to XML is quite effective. Try
var xml1 = XDocument.Load("File1.xml");
var xml2 = XDocument.Load("File2.xml");
foreach (XElement metNode in xml1.Descendants("ID"))
{
metNode.AddAfterSelf(xml2.Descendants("Path").Where(ele => ele.Value.Equals(metNode.Parent.Element("Path").Value)).FirstOrDefault().Parent.Element("Description"));
}
I have the following XSL:
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
<xsl:param name='width' select ="270"/>
<xsl:param name='height' select="180"/>
<xsl:variable name="counter" select="0" />
<xsl:template name="while">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<line x1="{$counter}" y1="0.5" x2="{$counter}" y2="10.5" stroke="black" stroke-width="1" />
<xsl:variable name="counter" select="$counter + 10" />
<xsl:if test="$counter < $width">
<xsl:call-template name="while"/>
</xsl:if>
</svg>
</xsl:template>
</xsl:stylesheet>
I'm trying to get a line drawn every 10pixels across the width, like ruler markings.
When I run this code, it gets stuck in a loop. I can't debug, I just get a stack overflow exception. I presume either my counter value isn't increasing by 10, or that my evaluation of checking if the counter < width is incorrect.
Can someone please point me in the right direction?
I think you need to pass the params when calling your template.
Something like:
<xsl:template name="loop">
<xsl:param name="count" select="1"/>
<xsl:if test="$count > 0">
<xsl:call-template name="loop">
<xsl:with-param name="count" select="$count - 1"/>
</xsl:call-template>
<xsl:value-of select="$count"/>
<xsl:text> </xsl:text>
</xsl:if>
</xsl:template>
You need to pass the count to your template by using xsl:with-param.
Example:
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
<xsl:output indent="yes"/>
<xsl:param name='width' select ="270"/>
<xsl:param name='height' select="180"/>
<xsl:template match="/">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<xsl:call-template name="while"/>
</svg>
</xsl:template>
<xsl:template name="while">
<xsl:param name="currentCount" select="0"/>
<line x1="{$currentCount}" y1="0.5" x2="{$currentCount}" y2="10.5" stroke="black" stroke-width="1" />
<xsl:variable name="counter" select="$currentCount + 10" />
<xsl:if test="$counter < $width">
<xsl:call-template name="while">
<xsl:with-param name="currentCount" select="$counter"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
My xslt transform does not pick up my document, this is because some/most elements are encoded,
e.g. my document:
<Template>
<ID>14</ID>
<Name>name of report</Name>
<VersionNumber>1.0</VersionNumber>
<CoverPage>
<br />
<br />
<h3 style="text-align: center;">
<br class="GENTICS_ephemera" />
</h3>
<h3 style="text-align: center;">
<br class="GENTICS_ephemera" />
</h3>
<h3 style="text-align: center;">Property Valuation Report</h3>
</CoverPage>
</Template>
This will never work:
<xsl:template match="span">
<fo:inline>
<xsl:call-template name="tokenize-style"/>
<xsl:apply-templates select="*|text()"/>
</fo:inline>
</xsl:template>
<xsl:template match="br">
<fo:block>
<fo:leader />
</fo:block>
</xsl:template>
Question: How can I get my document in the corrent format (technically my xml is valid and in correct format) but I want to do an xsl transform so I need to be able to pick up the correct tags
Here is the method for my transform:
private static MemoryStream Transform(XNode xmlData, XNode xslt)
{
XmlWriter writer = null;
var xslTrans = new XslCompiledTransform();
try
{
//load the xsl
xslTrans.Load(xslt.CreateReader());
//create the output stream
var result = new MemoryStream();
writer = XmlWriter.Create(result, null);
//create the xml reader for the data
var data = xmlData.CreateReader();
//do the actual transform of xml
xslTrans.Transform(data, null, writer);
writer.Close();
return new MemoryStream(result.ToArray());
}
catch (Exception e)
{
var errors = XslErrors.GetCompileErrors(xslTrans);
if (errors == null)
{
// Failed to obtain list of compile errors
throw;
}
if (writer != null) writer.Close();
throw e;
}
}
Update My XSLT Doc...
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format" version="2.0"
xmlns:fp="http://example.com/fp"
exclude-result-prefixes="fp">
<xsl:output method="xml" indent="yes" omit-xml-declaration="no" />
<xsl:variable name="pagewidth" select="21.5"/>
<xsl:variable name="bodywidth" select="17"/>
<xsl:template match="Template">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" font-family="Arial" font-size="9pt" color="black">
<fo:layout-master-set>
<fo:simple-page-master master-name="Cover" page-height="29.7cm" page-width="21cm" margin-top="2cm" margin-bottom="2cm" margin-left="2cm" margin-right="2cm">
<fo:region-body/>
</fo:simple-page-master>
<fo:simple-page-master master-name="BodyContent" page-height="29.7cm" page-width="21cm">
<fo:region-body margin-top="2cm" margin-bottom="2cm" margin-left="2cm" margin-right="2cm"/>
<!-- Header -->
<fo:region-before margin-bottom="2cm" extent="5cm" padding="0cm" border-width="0cm"/>
<!-- Footer -->
<fo:region-after margin-top="2cm" extent="2cm" padding="0cm" border-width="0cm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="Cover">
<fo:flow flow-name="xsl-region-body" >
<fo:block id="CoverPageWrapper">
<xsl:apply-templates select="fp:ParseFragment(.)/node()"/>
<xsl:apply-templates select="CoverPage" />
</fo:block>
</fo:flow>
</fo:page-sequence>
<fo:page-sequence master-reference="BodyContent" initial-page-number="1">
<fo:static-content flow-name="xsl-region-before">
<fo:table margin-left="2cm" padding-top="1cm" table-layout="fixed" width="170mm">
<fo:table-column column-width="70mm" />
<fo:table-column column-width="100mm" />
<fo:table-body>
<fo:table-row>
<fo:table-cell padding-start="1pt" padding-end="1pt" padding-before="1pt" padding-after="1pt" padding-top="1pt" padding-bottom="1pt">
<fo:block-container width="3cm" height="2cm">
<fo:block>
</fo:block>
</fo:block-container>
</fo:table-cell>
<fo:table-cell padding-start="1pt" padding-end="1pt" padding-before="1pt" padding-after="1pt" padding-top="1pt" padding-bottom="1pt">
<fo:block-container width="4cm" height="2.2cm">
<fo:block>
</fo:block>
</fo:block-container>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:static-content>
<fo:static-content flow-name="xsl-region-after">
<fo:block text-align="center" font-size="8pt" padding-top="0.5cm">
Page
<fo:page-number/>
of
<fo:page-number-citation ref-id="FinalPage"/>
</fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block id="BodyContentWrapper">
<xsl:apply-templates select="Body" />
</fo:block>
<!-- End of the document stuff that is needed-->
<fo:block id="FinalPage"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="label[#data-field-class='ui-templatefield']">
<xsl:choose>
<xsl:when test="#fo-checkbox" >
<xsl:choose>
<xsl:when test="text()='True'">
<fo:inline font-size="9pt" color="black">
[
<fo:inline font-family="ZapfDingbats" border-color="black" border-style="solid" border-width="1pt" font-size="6pt">✕</fo:inline>
]
</fo:inline>
</xsl:when>
<xsl:otherwise>
<fo:inline>
[ ]
<!-->fo:inline font-family="ZapfDingbats" font-size="10pt">❏</fo:inline-->
</fo:inline>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<fo:inline>
<xsl:apply-templates select="*|text()"/>
</fo:inline>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="span">
<fo:inline>
<xsl:call-template name="tokenize-style"/>
<xsl:apply-templates select="*|text()"/>
</fo:inline>
</xsl:template>
<xsl:template match="blockquote">
<fo:block
space-before="6pt" space-after="6pt"
start-indent="1em" end-indent="1em">
<xsl:apply-templates select="*|text()"/>
</fo:block>
</xsl:template>
<xsl:template match="h1">
<fo:block font-size="22pt">
<xsl:call-template name="tokenize-style"/>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="h2">
<fo:block font-size="18pt">
<xsl:call-template name="tokenize-style"/>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="h3">
<fo:block font-size="16pt">
<xsl:call-template name="tokenize-style"/>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="h4">
<fo:block font-size="14pt">
<xsl:call-template name="tokenize-style"/>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="h5">
<fo:block font-size="12pt" font-weight="bold">
<xsl:call-template name="tokenize-style"/>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="h6">
<fo:block font-size="10pt" font-weight="bold">
<xsl:call-template name="tokenize-style"/>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template name="tokenize-style">
<xsl:param name="pString" select="string(#style)"/>
<xsl:choose>
<xsl:when test="not($pString)"/>
<xsl:when test="contains($pString,';')">
<xsl:call-template name="tokenize-style">
<xsl:with-param name="pString"
select="substring-before($pString,';')"/>
</xsl:call-template>
<xsl:call-template name="tokenize-style">
<xsl:with-param name="pString"
select="substring-after($pString,';')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="{normalize-space(substring-before($pString,':'))}">
<xsl:value-of select="normalize-space(substring-after($pString,':'))"/>
</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="div">
<fo:block>
<xsl:if test="#class='bordered'">
<xsl:attribute name="border-width">1pt</xsl:attribute>
<xsl:attribute name="border-style">solid</xsl:attribute>
</xsl:if>
<xsl:call-template name="tokenize-style"/>
<xsl:apply-templates select="*|text()"/>
</fo:block>
</xsl:template>
<xsl:template match="p" >
<fo:block space-before="4pt" space-after="4pt">
<xsl:call-template name="tokenize-style"/>
<xsl:apply-templates select="*|text()"/>
</fo:block>
</xsl:template>
<xsl:template match="ol">
<fo:list-block start-indent="1cm" space-before="6pt" space-after="6pt">
<xsl:apply-templates/>
</fo:list-block>
</xsl:template>
<xsl:template match="ol/li">
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<fo:block>
<xsl:choose>
<xsl:when test="../#type != ''">
<xsl:number format="{../#type}"/>.
</xsl:when>
<xsl:otherwise>
<xsl:number format="1"/>.
</xsl:otherwise>
</xsl:choose>
</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block font-size="11pt" color="black" font-family="Arial, Verdana, sans-serif">
<xsl:apply-templates/>
</fo:block>
</fo:list-item-body>
</fo:list-item>
</xsl:template>
<xsl:template match="ul">
<fo:list-block start-indent="1cm" space-before="6pt" space-after="6pt">
<xsl:apply-templates/>
</fo:list-block>
</xsl:template>
<xsl:template match="ul/li">
<fo:list-item>
<fo:list-item-label end-indent="label-end()">
<xsl:choose>
<xsl:when test="../#type ='disc'">
<fo:block>•</fo:block>
</xsl:when>
<xsl:when test="../#type='square'">
<fo:block font-family="ZapfDingbats">n</fo:block>
</xsl:when>
<xsl:when test="../#type='circle'">
<fo:block font-family="ZapfDingbats">m</fo:block>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="count(ancestor::ul) = 1">
<fo:block>•</fo:block>
</xsl:when>
<xsl:when test="count(ancestor::ul) = 2">
<fo:block font-family="ZapfDingbats">m</fo:block>
</xsl:when>
<xsl:otherwise>
<fo:block font-family="ZapfDingbats">n</fo:block>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</fo:list-item-body>
</fo:list-item>
</xsl:template>
<xsl:template match="dl">
<fo:block space-before="6pt" space-after="6pt">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="dt">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="dd">
<fo:block start-indent="5mm">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="table">
<fo:table>
<xsl:attribute name="width">
<xsl:text>170mm</xsl:text>
</xsl:attribute>
<xsl:apply-templates select="*|text()"/>
</fo:table>
</xsl:template>
<xsl:template match="caption">
<fo:caption>
<fo:block>
<xsl:apply-templates />
</fo:block>
</fo:caption>
</xsl:template>
<xsl:template match="colgroup">
<xsl:for-each select="col">
<fo:table-column>
<xsl:attribute name="column-width">
<xsl:choose>
<xsl:when test="contains(#width, '%')">
<xsl:value-of disable-output-escaping="yes" select="floor(number(translate(#width,'%','')) div 100 * $bodywidth)"/>
<xsl:text>cm</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of disable-output-escaping="yes" select="floor(#width div 72)"/>
<xsl:text>in</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</fo:table-column>
</xsl:for-each>
</xsl:template>
<xsl:template match="tbody">
<fo:table-body>
<xsl:apply-templates select="*|text()"/>
</fo:table-body>
</xsl:template>
<xsl:template match="tr">
<fo:table-row>
<xsl:apply-templates select="*|text()"/>
</fo:table-row>
</xsl:template>
<xsl:template match="th">
<fo:table-cell font-weight="bold" text-align="center">
<xsl:if test="ancestor::table/#border > 0">
<xsl:attribute name="border-style">solid</xsl:attribute>
<xsl:attribute name="border-width">0.1mm</xsl:attribute>
</xsl:if>
<fo:block>
<xsl:apply-templates select="*|text()"/>
</fo:block>
</fo:table-cell>
</xsl:template>
<xsl:template match="td">
<fo:table-cell padding-start="1pt" padding-end="1pt" padding-before="1pt" padding-after="1pt" padding-top="1pt" padding-bottom="1pt">
<xsl:if test="ancestor::table/#border > 0">
<xsl:attribute name="border-style">solid</xsl:attribute>
<xsl:attribute name="border-width">0.1mm</xsl:attribute>
</xsl:if>
<xsl:if test="ancestor::tr/#class='titleformat'">
<xsl:attribute name="background-color">black</xsl:attribute>
<xsl:attribute name="color">white</xsl:attribute>
<xsl:attribute name="font-size">9pt</xsl:attribute>
</xsl:if>
<fo:block>
<xsl:apply-templates select="*|text()"/>
</fo:block>
</fo:table-cell>
</xsl:template>
<xsl:template match="tt">
<fo:inline font-family="monospace">
<xsl:apply-templates select="*|text()"/>
</fo:inline>
</xsl:template>
<xsl:template match="img">
<fo:external-graphic>
<xsl:attribute name="src">
file:<xsl:value-of
select="#src"/>
</xsl:attribute>
<xsl:attribute name="width">
<xsl:value-of
select="#width"/>px
</xsl:attribute>
<xsl:attribute name="height">
<xsl:value-of
select="#height"/>px
</xsl:attribute>
</fo:external-graphic>
</xsl:template>
<xsl:template match="pre">
<fo:block white-space-collapse="false">
<xsl:apply-templates select="*|text()"/>
</fo:block>
</xsl:template>
<xsl:template match="b">
<fo:inline>
<xsl:attribute name="font-weight">bold</xsl:attribute>
<xsl:apply-templates select="*|text()"/>
</fo:inline>
</xsl:template>
<xsl:template match="i">
<fo:inline>
<xsl:attribute name="font-style">italic</xsl:attribute>
<xsl:apply-templates select="*|text()"/>
</fo:inline>
</xsl:template>
<xsl:template match="hr">
<xsl:if test="#class='ui-pagebreak'">
<fo:block break-after="page" />
</xsl:if>
<xsl:if test="#class=''">
<fo:block>
<fo:leader
leader-pattern="rule" leader-length.optimum="100%"
rule-style="double" rule-thickness="1pt"/>
</fo:block>
</xsl:if>
</xsl:template>
<xsl:template match="br">
<fo:block>
<fo:leader />
</fo:block>
</xsl:template>
</xsl:stylesheet>
Here is an example with XslCompiledTransform and an extension object:
class Program
{
static void Main(string[] args)
{
XslCompiledTransform proc = new XslCompiledTransform();
proc.Load("../../XSLTFile1.xslt");
XsltArgumentList xsltArgs = new XsltArgumentList();
xsltArgs.AddExtensionObject("http://example.com/fp", new FragmentParser());
proc.Transform("../../XMLFile1.xml", xsltArgs, Console.Out);
}
}
public class FragmentParser
{
public IXPathNavigable ParseFragment(string fragment)
{
XmlDocument doc = new XmlDocument();
XmlDocumentFragment frag = doc.CreateDocumentFragment();
frag.InnerXml = fragment;
return frag;
}
}
then in your stylesheet you can use code as the following:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fp="http://example.com/fp"
exclude-result-prefixes="fp"
>
<xsl:template match="CoverPage">
<Test>
<xsl:apply-templates select="fp:ParseFragment(.)/node()"/>
</Test>
</xsl:template>
<xsl:template match="h3">
<heading>
<xsl:apply-templates/>
</heading>
</xsl:template>
</xsl:stylesheet>
[edit]
In your stylesheet you can change
<fo:page-sequence master-reference="Cover">
<fo:flow flow-name="xsl-region-body" >
<fo:block id="CoverPageWrapper">
<xsl:apply-templates select="fp:ParseFragment(.)/node()"/>
<xsl:apply-templates select="CoverPage" />
</fo:block>
</fo:flow>
</fo:page-sequence>
to
<fo:page-sequence master-reference="Cover">
<fo:flow flow-name="xsl-region-body" >
<fo:block id="CoverPageWrapper">
<xsl:apply-templates select="fp:ParseFragment(CoverPage)/node()"/>
</fo:block>
</fo:flow>
</fo:page-sequence>
Or add a template for CoverPage e.g.
<xsl:template match="CoverPage">
<xsl:apply-templates select="fp:ParseFragment(.)/node()"/>
</xsl:template>
and then above you would simply do e.g.
<fo:page-sequence master-reference="Cover">
<fo:flow flow-name="xsl-region-body" >
<fo:block id="CoverPageWrapper">
<xsl:apply-templates select="CoverPage" />
</fo:block>
</fo:flow>
</fo:page-sequence>
I get this Exception when in try to convert data relation from Data set tables to xml to make an XmlDataSource supply it to Dynamic Menu Control.
This is the Code behind
DataSet ds = new DataSet();
SqlCommand cmdmenu = new SqlCommand("select CategoryID,CategoryName from Category ", ConManager.Con());
SqlCommand com2 = new SqlCommand("select CategoryIDToSub,subcategoryid ,SubCategoryName from CategorySub", ConManager.Con());
SqlCommand cmd3 = new SqlCommand("select subcategoryid 'SubCategoryID2',Sub2CategoryName from CategorySub2", ConManager.Con());
SqlDataAdapter menadapter = new SqlDataAdapter(cmdmenu.CommandText, ConManager.Con());
SqlDataAdapter menadapter2 = new SqlDataAdapter(com2.CommandText, ConManager.Con());
SqlDataAdapter menadapter3 = new SqlDataAdapter(cmd3.CommandText, ConManager.Con());
menadapter.Fill(ds, "Menu");
menadapter.SelectCommand = com2;
menadapter2.Fill(ds, "SubMenu");
menadapter3.SelectCommand = cmd3;
menadapter3.Fill(ds, "SubSubMenu");
DataColumn colParent =
ds.Tables["Menu"].Columns["CategoryID"];
DataColumn colChild =
ds.Tables["SubMenu"].Columns["CategoryIDToSub"];
DataRelation relation = new DataRelation("relationName",
colParent,
colChild, true);
DataRelation Relation2 = new DataRelation("relationName2",
ds.Tables["SubMenu"].Columns["subcategoryid"],
ds.Tables["SubSubMenu"].Columns["SubCategoryID2"], true);
relation.Nested = true;
Relation2.Nested = true;
ds.Relations.Add(relation);
ds.Relations.Add(Relation2);
XmlDataSource.Data = ds.GetXml();
if (Request.Params["Sel"] != null)
Page.Controls.Add(new System.Web.UI.LiteralControl("You selected " + Request.Params["Sel"]));
and this is the Xslt File Code
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="utf-8"/>
<!-- Replace root node name Menus with MenuItems
and call MenuListing for its children-->
<xsl:template match="/Menus">
<MenuItems>
<xsl:call-template name="MenuListing" />
</MenuItems>
</xsl:template>
<!-- Allow for recursive child nodeprocessing -->
<xsl:template name="MenuListing">
<xsl:apply-templates select="Menu" />
</xsl:template>
<xsl:template match="Menu">
<MenuItem>
<!-- Convert Menu child elements to MenuItem attributes -->
<xsl:attribute name="Text">
<xsl:value-of select="CategoryName"/>
</xsl:attribute>
<xsl:attribute name="ToolTip">
<xsl:value-of select="Remarks"/>
</xsl:attribute>
<xsl:attribute name="NavigateUrl">
<xsl:text>?Sel=</xsl:text>
<xsl:value-of select="Text"/>
</xsl:attribute>
<xsl:attribute name="Text2">
<xsl:value-of select="SubCategoryName"/>
</xsl:attribute>
<xsl:attribute name="Test3">
<xsl:value-of select="Sub2CategoryName3"/>
</xsl:attribute>
<!-- Recursively call MenuListing forchild menu nodes -->
<xsl:if test="count(Menu) >0">
<xsl:call-template name="MenuListing" />
</xsl:if>
</MenuItem>
</xsl:template>
</xsl:stylesheet>
and this is the Menu Control and the XmlDataSource Code
<asp:Menu ID="Menu" runat="server" BackColor="#E3EAEB" DynamicHorizontalOffset="2" Font-Names="Verdana" Font-Size="0.8em" ForeColor="#666666" StaticSubMenuIndent="10px" DataSourceID="XmlDataSource" Width="225px" onmenuitemclick="Menu_MenuItemClick">
<DataBindings>
<asp:MenuItemBinding DataMember="MenuItem" NavigateUrlField="NavigateUrl" TextField="Text" />
<asp:MenuItemBinding DataMember="MenuItem" NavigateUrlField="NavigateUrl" TextField="Text2" />
<asp:MenuItemBinding DataMember="MenuItem" NavigateUrlField="NavigateUrl" TextField="Text3" />
</DataBindings>
<StaticSelectedStyle BackColor="#1C5E55" />
<StaticMenuItemStyle HorizontalPadding="5px" VerticalPadding="2px" />
<DynamicHoverStyle BackColor="#666666" ForeColor="White" />
<DynamicMenuStyle BackColor="#E3EAEB" />
<DynamicSelectedStyle BackColor="#1C5E55" />
<DynamicMenuItemStyle HorizontalPadding="5px" VerticalPadding="2px" />
<StaticHoverStyle BackColor="#666666" ForeColor="White" />
</asp:Menu>
<asp:XmlDataSource ID="XmlDataSource" runat="server"
TransformFile="~/TransformXSLT.xsl" XPath="MenuItems/MenuItem">
</asp:XmlDataSource>
Your XML document is not well formed. You have more than one document (root) element. For example:
<a>some</a>
<a>thing</a>
is not well formed. Whereas:
<list>
<a>some</a>
<a>thing</a>
</list>
is well formed.