How can I transform XML to invalid XML using XSLT? - c#

I need to transform a valid XML document to the OFX v1.0.2 format. This format is more or less XML, but it's technically invalid and therefore cannot be parsed as XML.
I'm having trouble getting my Xml transformation working because the .Net XslCompiledTransform object insists on interpreting the output as an XML document (which is fair enough).
**Here's my function to transform the Xml
public string Transform(XmlElement xmlElement, Dictionary<string, object> parameters)
{
string strReturn = "";
// Set the settings to allow scripts to executed.
XsltSettings settings = new XsltSettings(false, true);
// Load the XSLT Document
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(xsltFileName, settings, new XmlUrlResolver());
// arguments
XsltArgumentList args = new XsltArgumentList();
if (parameters != null && parameters.Count > 0)
{
foreach (string key in parameters.Keys)
{
args.AddParam(key, "", parameters[key]);
}
}
//Create a memory stream to write to
Stream objStream = new MemoryStream();
// Transform the xml/xslt into a Writer
XmlTextWriter xmlWriter = new XmlTextWriter(objStream, Encoding.UTF8);
// Apply the transform
xslt.Transform(xmlElement, args, xmlWriter);
objStream.Seek(0, SeekOrigin.Begin);
// Read the contents of the stream
StreamReader objSR = new StreamReader(objStream);
strReturn = objSR.ReadToEnd();
return strReturn;
}
If I escape the xml-ish tags using < and &gt, they get removed when I download the file.
Here's the start of my XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"></xsl:output>
<xsl:param name="currentdate"></xsl:param>
<xsl:template match="Transactions">
OFXHEADER:100
DATA:OFXSGML
VERSION:102
SECURITY:NONE
ENCODING:USASCII
CHARSET:1252
COMPRESSION:NONE
OLDFILEUID:NONE
NEWFILEUID:NONE
<OFX>
<SIGNONMSGSRSV1>
<SONRS>
<STATUS>
<CODE>0
<SEVERITY>INFO
</STATUS>
<DTSERVER><xsl:value-of select="$currentdate" />
<LANGUAGE>ENG
So can I transform my XML to a plain text string?
UPDATE:
I've changed this question. I just realised the obvious answer to the original question. Using the XslCompiledTransform object requires me to write the output to an Xml document using an XmlTextWriter. Obviously it won't parse. Apologies.

Xslt can output text; just make sure that you set the output-mode of the xslt to text, and wriet to a TextWriter (there are multiple overloads available). Writing something that is nearly xml in xslt is painful, but possible with disabling the escape rules.
Here's an example (albeit ugly) xslt for writing non-xml:
<?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="text" indent="yes"/>
<xsl:template match="#* | node()">
<xsl:call-template name="startElement">
<xsl:with-param name="name" select="'SONRS'"/>
</xsl:call-template>
<xsl:call-template name="startElement">
<xsl:with-param name="name" select="'STATUS'"/>
<xsl:with-param name="value" select="0"/>
</xsl:call-template>
<xsl:call-template name="startElement">
<xsl:with-param name="name" select="'SEVERITY'"/>
<xsl:with-param name="value" select="'INFO'"/>
</xsl:call-template>
<xsl:call-template name="endElement">
<xsl:with-param name="name" select="'SONRS'"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="startElement">
<xsl:param name="name"/>
<xsl:param name="value"/>
<xsl:text disable-output-escaping="yes"><</xsl:text>
<xsl:value-of select="$name"/>
<xsl:text disable-output-escaping="yes">></xsl:text>
<xsl:value-of select="$value"/>
</xsl:template>
<xsl:template name="endElement">
<xsl:param name="name"/>
<xsl:text disable-output-escaping="yes"></</xsl:text>
<xsl:value-of select="$name"/>
<xsl:text disable-output-escaping="yes">></xsl:text>
</xsl:template>
</xsl:stylesheet>

Related

Valid XSL Transform won't parse in c#

I have this XML input:
<?xml version="1.0"?>
<xc:XmlCache xmlns:xc="XmlCache" xmlns:mp="mx.MarketParameters" xmlns:rt="mx.MarketParameters.Rates" xmlns:rtcu="mx.MarketParameters.Rates.Curve">
<xc:XmlCacheArea xc:value="MarketParameters">
<mp:nickName xmlns:mp="mx.MarketParameters" xc:value="BO">
<mp:date xc:value="20211208">
<rt:rate xmlns:rt="mx.MarketParameters.Rates">
<rtcu:curve xmlns:rtcu="mx.MarketParameters.Rates.Curve">
<rtcu:currency xc:value="USD">
<rtcu:label xc:value="USD: SOV_ZC">
<rtcu:type xc:value="Swap">
<rtcu:generator xc:value="USD S TREAS">
<rtcu:market xc:value="">
<rtcu:maturity xc:value="10Y" xc:dates="20211210-20311210" xc:type="Fields">
<mp:askConvexitySpread xc:keyFormat="N">0</mp:askConvexitySpread>
<mp:askCurveSpread xc:keyFormat="N">0.000000000</mp:askCurveSpread>
<mp:askDiscount xc:keyFormat="N">0.864632927818374</mp:askDiscount>
<mp:askDiscountBasisSpread xc:keyFormat="N"/>
<mp:askMarketQuote xc:keyFormat="N">1.446068284</mp:askMarketQuote>
<mp:askZeroCoupon xc:keyFormat="N">1.45291000006736</mp:askZeroCoupon>
<mp:askZeroCouponBasisSpread xc:keyFormat="N"/>
<mp:askZeroCouponSpread xc:keyFormat="N">0.000000000</mp:askZeroCouponSpread>
<mp:bidConvexitySpread xc:keyFormat="N">0</mp:bidConvexitySpread>
<mp:bidCurveSpread xc:keyFormat="N">0.000000000</mp:bidCurveSpread>
<mp:bidDiscount xc:keyFormat="N">0.864632927818374</mp:bidDiscount>
<mp:bidDiscountBasisSpread xc:keyFormat="N"/>
<mp:bidMarketQuote xc:keyFormat="N">1.446068284</mp:bidMarketQuote>
<mp:bidZeroCoupon xc:keyFormat="N">1.45291000006736</mp:bidZeroCoupon>
<mp:bidZeroCouponBasisSpread xc:keyFormat="N"/>
<mp:bidZeroCouponSpread xc:keyFormat="N">0.000000000</mp:bidZeroCouponSpread>
<mp:frontierDate xc:keyFormat="N">0</mp:frontierDate>
<mp:intervalSplineEta xc:keyFormat="N">-1</mp:intervalSplineEta>
<mp:midConvexitySpread xc:keyFormat="N">0</mp:midConvexitySpread>
<mp:midCurveSpread xc:keyFormat="N">0.000000000</mp:midCurveSpread>
<mp:midDiscount xc:keyFormat="N">0.864632927818374</mp:midDiscount>
<mp:midDiscountBasisSpread xc:keyFormat="N"/>
<mp:midMarketQuote xc:keyFormat="N">1.446068284</mp:midMarketQuote>
<mp:midZeroCoupon xc:keyFormat="N">1.45291000006736</mp:midZeroCoupon>
<mp:midZeroCouponBasisSpread xc:keyFormat="N"/>
<mp:midZeroCouponSpread xc:keyFormat="N">0.000000000</mp:midZeroCouponSpread>
<mp:selected xc:keyFormat="N">1</mp:selected>
</rtcu:maturity>
<rtcu:maturity xc:value="15Y" xc:dates="20211210-20361210" xc:type="Fields">
<mp:askConvexitySpread xc:keyFormat="N">0</mp:askConvexitySpread>
<mp:askCurveSpread xc:keyFormat="N">0.000000000</mp:askCurveSpread>
<mp:askDiscount xc:keyFormat="N">0.769521955887512</mp:askDiscount>
<mp:askDiscountBasisSpread xc:keyFormat="N"/>
<mp:askMarketQuote xc:keyFormat="N">1.716406662</mp:askMarketQuote>
<mp:askZeroCoupon xc:keyFormat="N">1.74466000012162</mp:askZeroCoupon>
<mp:askZeroCouponBasisSpread xc:keyFormat="N"/>
<mp:askZeroCouponSpread xc:keyFormat="N">0.000000000</mp:askZeroCouponSpread>
<mp:bidConvexitySpread xc:keyFormat="N">0</mp:bidConvexitySpread>
<mp:bidCurveSpread xc:keyFormat="N">0.000000000</mp:bidCurveSpread>
<mp:bidDiscount xc:keyFormat="N">0.769521955887512</mp:bidDiscount>
<mp:bidDiscountBasisSpread xc:keyFormat="N"/>
<mp:bidMarketQuote xc:keyFormat="N">1.716406662</mp:bidMarketQuote>
<mp:bidZeroCoupon xc:keyFormat="N">1.74466000012162</mp:bidZeroCoupon>
<mp:bidZeroCouponBasisSpread xc:keyFormat="N"/>
<mp:bidZeroCouponSpread xc:keyFormat="N">0.000000000</mp:bidZeroCouponSpread>
<mp:frontierDate xc:keyFormat="N">0</mp:frontierDate>
<mp:intervalSplineEta xc:keyFormat="N">-1</mp:intervalSplineEta>
<mp:midConvexitySpread xc:keyFormat="N">0</mp:midConvexitySpread>
<mp:midCurveSpread xc:keyFormat="N">0.000000000</mp:midCurveSpread>
<mp:midDiscount xc:keyFormat="N">0.769521955887512</mp:midDiscount>
<mp:midDiscountBasisSpread xc:keyFormat="N"/>
<mp:midMarketQuote xc:keyFormat="N">1.716406662</mp:midMarketQuote>
<mp:midZeroCoupon xc:keyFormat="N">1.74466000012162</mp:midZeroCoupon>
<mp:midZeroCouponBasisSpread xc:keyFormat="N"/>
<mp:midZeroCouponSpread xc:keyFormat="N">0.000000000</mp:midZeroCouponSpread>
<mp:selected xc:keyFormat="N">1</mp:selected>
</rtcu:maturity>
</rtcu:market>
</rtcu:generator>
</rtcu:type>
</rtcu:label>
</rtcu:currency>
</rtcu:curve>
</rt:rate>
</mp:date>
</mp:nickName>
</xc:XmlCacheArea>
</xc:XmlCache>
I am using this transform :
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:mp="mx.MarketParameters" xmlns:xc="xmlCache" xmlns:rt="mx.MarketParameters.Rates" xmlns:rtcu="mx.MarketParameters.Rates.Curve">
<xsl:template match="/">
<data>
<xsl:apply-templates select="*"/>
</data>
</xsl:template>
<xsl:template match="rtcu:maturity">
<row>
<xsl:attribute name="Cle"><xsl:value-of select="../../../../../#*:value"/>;<xsl:value-of select="../../../../#*:value"/>;<xsl:value-of select="../../../#*:value"/>;<xsl:value-of select="../../#*:value"/>;<xsl:value-of select="../#*:value"/>;<xsl:value-of select="#*:value"/></xsl:attribute>
<xsl:attribute name="Source1"><xsl:value-of select="mp:askZeroCoupon"/></xsl:attribute>
<xsl:attribute name="Source2"><xsl:value-of select="mp:bidZeroCoupon"/></xsl:attribute>
<xsl:attribute name="Source3"><xsl:value-of select="mp:midZeroCoupon"/></xsl:attribute>
</row>
</xsl:template>
</xsl:stylesheet>
And the result is as expected when I use the validator here: https://www.freeformatter.com/xsl-transformer.html
<data xmlns:mp="mx.MarketParameters"
xmlns:xc="xmlCache"
xmlns:rt="mx.MarketParameters.Rates"
xmlns:rtcu="mx.MarketParameters.Rates.Curve">
<row Cle="USD;USD: SOV_ZC;Swap;USD S TREAS;;10Y"
Source1="1.45291000006736"
Source2="1.45291000006736"
Source3="1.45291000006736"/>
<row Cle="USD;USD: SOV_ZC;Swap;USD S TREAS;;15Y"
Source1="1.74466000012162"
Source2="1.74466000012162"
Source3="1.74466000012162"/>
</data>
However when I run this transform in a C# app and call the Load() function in XslCompiledTransform when I pass it this transform above, it fails with the error
Expected end of the expression, found `':'.\r\n../../../../../#* -->:<--`
It basically refuses to check the other namespaces for the attribute I'm looking for on this node.
I know that the attributes are in the xc namespace but when I use the xc: namespace to get the attribute values to build my key like so:
<xsl:value-of select="#xc:value"/>
The values are all null which results in a key that looks like this in the output:
<row Cle=";;;;;"
No bueno!
How can I output the values of all the xc:value attributes from these tags:
<rtcu:currency xc:value="USD">
<rtcu:label xc:value="USD: SOV_ZC">
<rtcu:type xc:value="Swap">
<rtcu:generator xc:value="USD S TREAS">
<rtcu:market xc:value="">
<rtcu:maturity xc:value="10Y"
into my key row:
<row Cle="USD;USD: SOV_ZC;Swap;USD S TREAS;;10Y"
while not triggering a parsing error in the c# Load() function?
There are two errors in your code:
Namespace wildcards like *:value are a feature of XPath-2.0 and above
Local name tests (namespace wildcards) were eventually added to XPath 2.0
So you can't use them in your XSLT-1.0 code
You have a typo in your xc: namespace declaration:
In your XML it's xmlns:xc="XmlCache"
In your XSLT it's xmlns:xc="xmlCache"
If you fix both, the code should work as desired.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:mp="mx.MarketParameters" xmlns:xc="XmlCache" xmlns:rt="mx.MarketParameters.Rates" xmlns:rtcu="mx.MarketParameters.Rates.Curve">
<xsl:template match="/">
<data>
<xsl:apply-templates select="*"/>
</data>
</xsl:template>
<xsl:template match="rtcu:maturity">
<row>
<xsl:attribute name="Cle"><xsl:value-of select="../../../../../#xc:value"/>;<xsl:value-of select="../../../../#xc:value"/>;<xsl:value-of select="../../../#xc:value"/>;<xsl:value-of select="../../#xc:value"/>;<xsl:value-of select="../#xc:value"/>;<xsl:value-of select="#xc:value"/></xsl:attribute>
<xsl:attribute name="Source1"><xsl:value-of select="mp:askZeroCoupon"/></xsl:attribute>
<xsl:attribute name="Source2"><xsl:value-of select="mp:bidZeroCoupon"/></xsl:attribute>
<xsl:attribute name="Source3"><xsl:value-of select="mp:midZeroCoupon"/></xsl:attribute>
</row>
</xsl:template>
</xsl:stylesheet>
BTW you can simplify one of your expressions to
<xsl:attribute name="Cle"><xsl:for-each select="ancestor-or-self::rtcu:*"><xsl:value-of select="#xc:value"/><xsl:if test="position()!=last() and position()!=1">;</xsl:if></xsl:for-each></xsl:attribute>
This concatenates the xc:value attributes of all rtcu:* ancestors. Maybe that's of some use to you.

How to use variable and param of XSL 1.0

I get an error when I am studying XSL through C#, and I don't know how to fix.
I knwo there are some XSL syntax errors, but I don't know how to fix it afer searching some XSL docs.
Following are sample code of XML/XSL/C#.
Test XML file, Books.xml
<?xml version='1.0'?>
<Books>
<Publishers>
<Level1Publishers>
<PublisherA>
<Book bid="A1"><Name>Test Book from A</Name></Book>
</PublisherA>
<PublisherB>
<Book bid="B1"><Name>Test Book from B</Name></Book>
</PublisherB>
</Level1Publishers>
</Publishers>
</Books>
XSL file, Books.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:param name="PUBLISHER_NAME"/>
<xsl:template match="//Publishers">
<xsl:variable name="PUBLISHER_PATH" select="./Level1Publishers/$PUBLISHER_NAME/Book"/>
<Book>
<BookId>
<xsl:value-of select="$PUBLISHER_PATH/#bid"/>
</BookId>
<Name>
<xsl:value-of select="$PUBLISHER_PATH/Name"/>
</Name>
</Book>
</xsl:template>
</xsl:stylesheet>
C# code to perform the transformation
using System;
using System.IO;
using System.Xml.Xsl;
namespace TestXSL
{
class Program
{
static void Main(string[] ags)
{
XsltArgumentList args = new XsltArgumentList();
args.AddParam("PUBLISHER_NAME", "", "PublisherB");
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load("Books.xsl");
StringWriter writer = new StringWriter();
xslt.Transform("Books.xml", args, writer);
Console.WriteLine(writer.ToString());
}
}
}
It reports exception when load XSL file.
Unhandled Exception: System.Xml.Xsl.XslLoadException: Unexpected token '$' in the expression.
./Level1Publishers/ -->$<-- PUBLISHER_NAME/Book
at System.Xml.Xsl.XslCompiledTransform.LoadInternal(Object stylesheet, XsltSettings settings, XmlResolver stylesheetResolver)
at System.Xml.Xsl.XslCompiledTransform.Load(String stylesheetUri)
at TestXSL.Program.Main(String[] ags) in Program.cs:line 14
I then change the define PUBLISHER_PATH in the following way.
<xsl:variable name="PUBLISHER_PATH" select="concat('./Level1Publishers/',$PUBLISHER_NAME,'/Book')"/>
It reports another exception, it seems no syntax errors, but runtime error
Unhandled Exception: System.Xml.Xsl.XslTransformException: Expression must evaluate to a node-set.
at System.Xml.Xsl.Runtime.XsltConvert.EnsureNodeSet(IList`1 listItems)
at <xsl:template match="//Publishers">(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime)
at <xsl:apply-templates>(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime, XPathNavigator )
at <xsl:apply-templates>(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime, XPathNavigator )
at Root(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime)
at Execute(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime)
at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlSequenceWriter results)
at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter writer)
at System.Xml.Xsl.XslCompiledTransform.Transform(String inputUri, XsltArgumentList arguments, TextWriter results)
at TestXSL.Program.Main(String[] ags) in Program.cs:line 16
I hope this helps you.
<xsl:param name="PUBLISHER_NAME"/>
<xsl:template match="//Publishers/Level1Publishers">
<Book>
<BookId>
<xsl:value-of select=".//Book[Name=$PUBLISHER_NAME]/#bid"/>
</BookId>
<Name>
<xsl:value-of select="$PUBLISHER_NAME"/>
</Name>
</Book>
</xsl:template>
<xsl:template match="node()">
<xsl:apply-templates/>
</xsl:template>

XSLT: Howto output '<' and '>' from XSL transformation?

I am building some text snippets from XML documents using XSL transformation. The text can include '<' and '>' (and other special characters) in the output.
Given the following xml as data.xml:
<SCH>
<Ship Id="1" Name="Dicke Bertha" OperatingCostsDay="10.0000000" currency="USD" />
</SCH>
and the following xsl as transformation.xslt
<?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:template match="/">
Schiff: <xsl:for-each select="SCH/Ship"> Id: <xsl:value-of select="#Id"/>  <xsl:value-of select="#Name"/>  (OC:<xsl:value-of select="#OperatingCostsDay"/> <xsl:value-of select="#currency"/>)
</xsl:for-each>Betriebskosten < 500 USD oder > 1 Mio. USD
</xsl:template>
</xsl:stylesheet>
I have the problem that the escape sequences < and > when loading the XSLT:
var xslDocument = XDocument.Load("transformation.xslt");
The output after the transformation is not - as expected - with the '<' and '>' characters but it has the HTML escape sequences.
Schiff: Id: 1  Dicke Bertha  (OC:10.0000000 USD)
Betriebskosten < 500 USD oder > 1 Mio. USD
What can I do here?
For completeness, here is the full code example:
class Program
{
static void Main(string[] args)
{
var xslDocument = XDocument.Load("transformation.xslt");
var compiled = new XslCompiledTransform();
using (var reader = xslDocument.CreateReader())
{
compiled.Load(reader);
}
var xml = File.ReadAllText("data.xml");
Console.WriteLine(Transform(compiled, xml));
}
public static string Transform(XslCompiledTransform xsl, string xml)
{
// allow fragments
var writerSettings = new XmlWriterSettings { ConformanceLevel = ConformanceLevel.Auto };
var readerSettings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Auto };
var stringReader = new StringReader(xml);
var details = new StringBuilder();
using (var reader = XmlReader.Create(stringReader, readerSettings))
{
using (var writer = XmlWriter.Create(details, writerSettings))
{
xsl.Transform(reader, writer);
}
}
return details.ToString();
}
}
I am building some text snippets
If you are outputting text, then set your output method to text. Then your processor will know not to escape characters that are reserved in XML.
XSLT
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8" />
<xsl:template match="/">
Schiff: <xsl:for-each select="SCH/Ship"> Id: <xsl:value-of select="#Id"/>  <xsl:value-of select="#Name"/>  (OC:<xsl:value-of select="#OperatingCostsDay"/> <xsl:value-of select="#currency"/>)
</xsl:for-each>Betriebskosten < 500 USD oder > 1 Mio. USD
</xsl:template>
</xsl:stylesheet>
Result:
Schiff: Id: 1  Dicke Bertha  (OC:10.0000000 USD)
Betriebskosten < 500 USD oder > 1 Mio. USD
Note also that literal text is best put inside xsl:text instructions - otherwise you're passing all the unwanted surrounding whitespace to the output.
in XSLT, you can try like
Here I have added <xsl:text disable-output-escaping="yes"><</xsl:text> and <xsl:text disable-output-escaping="yes">></xsl:text>
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:template match="/">
Schiff: <xsl:for-each select="SCH/Ship"> Id: <xsl:value-of select="#Id"/>  <xsl:value-of select="#Name"/>  (OC:<xsl:value-of select="#OperatingCostsDay"/> <xsl:value-of select="#currency"/>)
</xsl:for-each> Betriebskosten <xsl:text disable-output-escaping="yes"><</xsl:text> 500 USD oder <xsl:text disable-output-escaping="yes">></xsl:text> 1 Mio. USD
</xsl:template>
</xsl:stylesheet>

How to pass document type parameter to xslt using saxon?

For sending atomic data types will use like
transformer.SetParameter(new QName("", "", customXml), new XdmAtomicValue("true"));
how to pass a XML/Node as a param to XSLT from C# ?
Can you please help me
followed your code it's working fine but i am getting only text inside the xml(what i am passing in parameter) but not Nodes
XSLT :
<xsl:param name="look-up" as="document-node()"/>
<xsl:template match="xpp:document">
<w:document xml:space="preserve">
<xsl:value-of select="$look-up"/>
</w:document>
</xsl:template>
XML
<?xml version="1.0" encoding="UTF-8"?>
<document version="1.0" xmlns="http://www.sdl.com/xpp">
//some tags
</document>
passing parameter (xml)
<Job>
</id>
</Job>
I think you should use the Processor object to construct an XdmNode, see the documentation which says:
The Processor provides a method NewDocumentBuilder which, as the name
implies, returns a DocumentBuilder. This may be used to construct a
document (specifically, an XdmNode) from a variety of sources. The
input can come from raw lexical XML by specifying a Stream or a Uri,
or it may come from a DOM document built using the Microsoft XML
parser by specifying an XmlNode, or it may be supplied
programmatically by nominating an XmlReader.
Then you can pass in the XdmNode to the SetParameter method http://saxonica.com/documentation/html/dotnetdoc/Saxon/Api/XsltTransformer.html#SetParameter%28Saxon.Api.QName,Saxon.Api.XdmValue%29 as XdmValue is a base class of XdmNode (XmlValue -> XdmItem -> XdmNode).
Here is an example that works for me with Saxon 9.5 HE on .NET:
Processor proc = new Processor();
DocumentBuilder db = proc.NewDocumentBuilder();
XsltTransformer trans;
using (XmlReader xr = XmlReader.Create("../../XSLTFile1.xslt"))
{
trans = proc.NewXsltCompiler().Compile(xr).Load();
}
XdmNode input, lookup;
using (XmlReader xr = XmlReader.Create("../../XMLFile1.xml"))
{
input = db.Build(xr);
}
using (XmlReader xr = XmlReader.Create("../../XMLFile2.xml"))
{
lookup = db.Build(xr);
}
trans.InitialContextNode = input;
trans.SetParameter(new QName("lookup-doc"), lookup);
using (XmlWriter xw = XmlWriter.Create(Console.Out))
{
trans.Run(new TextWriterDestination(xw));
}
The XSLT is
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:param name="lookup-doc"/>
<xsl:key name="map" match="map" use="key"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item">
<xsl:copy>
<xsl:value-of select="key('map', ., $lookup-doc)/value"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
the XML documents are
<root>
<item>foo</item>
</root>
and
<root>
<map>
<key>foo</key>
<value>bar</value>
</map>
</root>
the resulting output is
<root>
<item>bar</item>
</root>

Xml for txt file records

I am having a scenario to push the text records to db to track some information on an individual.
My text file contains the data as shown below:
logonID|agentName|modify|exception|start|stop|externalID
14051286759|Jacks, Monica|1373477063|Break|01:45|02:00|USWMAJ43
14051286759|Jacks, Monica|1373477063|Break|06:10|06:25|USWMAJ43
14051286759|Jacks, Monica|1373477063|Lunch|03:45|04:30|USWMAJ43
14051286759|Jacks, Monica|1373477063|Open|00:00|01:45|USWMAJ43
14051286759|Jacks, Monica|1373477063|Open|02:00|03:45|USWMAJ43
14051286759|Jacks, Monica|1373477063|Open|04:30|06:10|USWMAJ43
14051286759|Jacks, Monica|1373477063|Open|06:25|08:30|USWMAJ43
Now i need to create an XML for Break,Lunch and open(number of open for a record may vary about 5 to 6 entries) as:
<info>
<break>
<break_1>01:45-02:00</break_1>
<break_2>06:10-06:25</break_1>
</break>
<lunch>03:45-04:30</lunch>
<open>
<open_1>00:00-01:45</open_1>
<open_2>02:00-03:45</open_2>
<open_3>04:30-06:10</open_3>
<open_4>06:25-08:30</open_4>
</open>
</info>
Thanks in Advance
XSLT
To use the xslt you pass the file location to pText parameter, for example file:///C:/data.txt :
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pText" />
<xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:variable name="vText" select="unparsed-text($pText)"/>
<xsl:variable name="vLines" select="tokenize($vText, '\r?\n')[position() > 1][normalize-space()]"/>
<xsl:template match="/">
<info>
<xsl:for-each-group select="$vLines" group-by="tokenize(.,'\|')[4]">
<xsl:variable name="vKey" select="translate(current-grouping-key(), $uppercase, $smallcase)"/>
<xsl:element name="{$vKey}">
<xsl:for-each select="current-group()">
<xsl:variable name="vValues" select="tokenize(.,'\|')"/>
<xsl:variable name="vPos" select="position()"/>
<xsl:element name="{$vKey}_{$vPos}">
<xsl:value-of select="concat($vValues[5],'-',$vValues[6])"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:for-each-group>
</info>
</xsl:template>
</xsl:stylesheet>
Input:
logonID|agentName|modify|exception|start|stop|externalID
14051286759|Jacks, Monica|1373477063|Break|01:45|02:00|USWMAJ43
14051286759|Jacks, Monica|1373477063|Break|06:10|06:25|USWMAJ43
14051286759|Jacks, Monica|1373477063|Lunch|03:45|04:30|USWMAJ43
14051286759|Jacks, Monica|1373477063|Open|00:00|01:45|USWMAJ43
14051286759|Jacks, Monica|1373477063|Open|02:00|03:45|USWMAJ43
14051286759|Jacks, Monica|1373477063|Open|04:30|06:10|USWMAJ43
14051286759|Jacks, Monica|1373477063|Open|06:25|08:30|USWMAJ43
Output:
<info>
<break>
<break_1>01:45-02:00</break_1>
<break_2>06:10-06:25</break_2>
</break>
<lunch>
<lunch_1>03:45-04:30</lunch_1>
</lunch>
<open>
<open_1>00:00-01:45</open_1>
<open_2>02:00-03:45</open_2>
<open_3>04:30-06:10</open_3>
<open_4>06:25-08:30</open_4>
</open>
</info>
C#
Reference 1 and Reference 2
XsltArgumentList argsList = new XsltArgumentList();
argsList.AddParam("pText", "", "file:///C:/data.txt");
XPathDocument myXPathDoc = new XPathDocument(myXmlFile) ;
XslCompiledTransform myXslTrans = new XslCompiledTransform();
myXslTrans.Load(myStyleSheet);
XmlTextWriter myWriter = new XmlTextWriter("result.html",null);
myXslTrans.Transform(myXPathDoc,argsList,myWriter);

Categories

Resources