sign in | join about | help | sitemap
Connecting Tech Pros Worldwide
pintihar's Avatar

create xslt stylesheet in code


Question posted by: pintihar (Guest) on November 12th, 2005 03:04 AM
Hi,
As a follow on from an earlier post I have another question about
xslt.
Is it possible to create the stylsheet programatically? Is this
sensible? In the first phase I needed to map element name from inbound
xml to my internal elements to standardize disparate input.
Now I could just create an xslt stylesheet for each possible inbound
format and be done, but I think it would be powerful to be able store
this mapping in a database and programatically create the stylsheet.
This way I don't have to maintain potentially a great number of
stylesheets. The trouble is, I can't find any example where the
stylesheet is not Load'ed from a file.

Can someone provide an example of creating the stylesheet
programatically to pass to an XslTransform.Load method?
Do I just write out the XML to a string?

Maybe my example from before would help...

<?xml version="1.0" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:template match="NewDataSet" >
<MyDataSet>
<xsl:apply-templates select="Cust" />
</MyDataSet>
</xsl:template>
<xsl:template match="Cust">
<MyCustomer>
<xsl:apply-templates select="nameFirst" />
<xsl:apply-templates select="nameLast" />
<xsl:apply-templates select="addrCity" />
<xsl:apply-templates select="addrState" />
<xsl:apply-templates select="addrStreet" />
<xsl:apply-templates select="addrZIP" />
</MyCustomer>
</xsl:template>

<xsl:template match="nameFirst">
<MyFname>
<xsl:value-of select="text()" />
</MyFname>
</xsl:template>
<xsl:template match="nameLast">
<MyLname>
<xsl:value-of select="text()" />
</MyLname>
</xsl:template>
<xsl:template match="addrCity">
<MyCity>
<xsl:value-of select="text()" />
</MyCity>
</xsl:template>
<xsl:template match="addrState">
<MyState>
<xsl:value-of select="text()" />
</MyState>
</xsl:template>
<xsl:template match="addrStreet">
<MyStreet>
<xsl:value-of select="text()" />
</MyStreet>
</xsl:template>
<xsl:template match="addrZIP">
<MyZIPPO>
<xsl:value-of select="text()" />
</MyZIPPO>
</xsl:template>
</xsl:stylesheet>


Thanks in advance,
Pint
7 Answers Posted
Oleg Tkachenko [MVP]'s Avatar
Oleg Tkachenko [MVP] November 12th, 2005 03:04 AM
Guest - n/a Posts
#2: Re: create xslt stylesheet in code

pintihar wrote:
[color=blue]
> As a follow on from an earlier post I have another question about
> xslt.
> Is it possible to create the stylsheet programatically? Is this
> sensible? In the first phase I needed to map element name from inbound
> xml to my internal elements to standardize disparate input.
> Now I could just create an xslt stylesheet for each possible inbound
> format and be done, but I think it would be powerful to be able store
> this mapping in a database and programatically create the stylsheet.[/color]

Instead of creating stylesheet each time programatically (I'm not aware
of any of such facilities) you can go this way: define format of mapping
XML document, which defines required mapping and write (once) generic
stylesheet, which transforms documents basing on the mapping.
Alternatively you can have generic stylesheet, which generates specific
stylesheets according to provided mapping (that's very easy to generate
XSLT with XSLT).

--
Oleg Tkachenko [XML MVP, XmlInsider]
http://blog.tkachenko.com
pintihar's Avatar
Guest - n/a Posts
#3: Re: create xslt stylesheet in code

>> As a follow on from an earlier post I have another question about[color=blue][color=green]
>> xslt.
>> Is it possible to create the stylsheet programatically? Is this
>> sensible? In the first phase I needed to map element name from inbound
>> xml to my internal elements to standardize disparate input.
>> Now I could just create an xslt stylesheet for each possible inbound
>> format and be done, but I think it would be powerful to be able store
>> this mapping in a database and programatically create the stylsheet.[/color]
>
>Instead of creating stylesheet each time programatically (I'm not aware
>of any of such facilities) you can go this way: define format of mapping
>XML document, which defines required mapping and write (once) generic
>stylesheet, which transforms documents basing on the mapping.
>Alternatively you can have generic stylesheet, which generates specific
>stylesheets according to provided mapping (that's very easy to generate
>XSLT with XSLT).[/color]

Are you suggesting in the first case, that the mapping would imposed
on the writer of the inbound xml to conform to a known format? This is
not possible as I have no control over the format of the inbound xml,
Just that the element names will be predictable: City State, Zip...
But differ slightly based on the actual source of the file: fname
versus FirstName.

I like the sound of the later, but on my reading, it seems to restate
my question: How do I generate xslt?

Thanks again,
Phil
Oleg Tkachenko [MVP]'s Avatar
Oleg Tkachenko [MVP] November 12th, 2005 03:04 AM
Guest - n/a Posts
#4: Re: create xslt stylesheet in code

pintihar wrote:
[color=blue]
> Are you suggesting in the first case, that the mapping would imposed
> on the writer of the inbound xml to conform to a known format?[/color]

Nope, leave alone inbound XML, but define your own mapping XML, which
defines how to map inbound elements to outbound ones. Something like

<mapping>
<rule inbound="foo" outbound="bar"/>
</mapping>

Then in XSLT you can look up for mapping and output elements according
to rules:

<xsl:template match="*">
<xsl:variable name="rule"
select="document('mapping.xml')/mapping/rule[@inbound=name(current())]"/>
<xsl:choose>
<xsl:when test="$rule">
<xsl:element name="{$rule/@outbound}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:if>
<xsl:otherwise>
<!-- No mapping - copy as is -->
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
<xsl:otherwise>
</xsl:choose>
</xsl:template>

[color=blue]
> I like the sound of the later, but on my reading, it seems to restate
> my question: How do I generate xslt?[/color]

XSLT is XML, so the question is how to create XML with XSLT. The only
thing to note is xsl:namespace-alias instruction, which allows to alias
elements of generated XML to distinguish them from XSLT instructions:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias">

<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>

<xsl:template match="/">
<axsl:stylesheet>
<xsl:apply-templates/>
</axsl:stylesheet>
</xsl:template>

<xsl:template match="block">
<axsl:template match="{.}">
<fo:block><axsl:apply-templates/></fo:block>
</axsl:template>
</xsl:template>

</xsl:stylesheet>

--
Oleg Tkachenko [XML MVP, XmlInsider]
http://blog.tkachenko.com
pintihar's Avatar
Guest - n/a Posts
#5: Re: create xslt stylesheet in code

On Thu, 04 Mar 2004 19:07:26 +0200, "Oleg Tkachenko [MVP]"
<oleg@NO!SPAM!PLEASEtkachenko.com> wrote:
[color=blue]
>pintihar wrote:
>[color=green]
>> Are you suggesting in the first case, that the mapping would imposed
>> on the writer of the inbound xml to conform to a known format?[/color]
>
>Nope, leave alone inbound XML, but define your own mapping XML, which
>defines how to map inbound elements to outbound ones. Something like
>
><mapping>
> <rule inbound="foo" outbound="bar"/>
></mapping>
>
>Then in XSLT you can look up for mapping and output elements according
>to rules:
>
><xsl:template match="*">
> <xsl:variable name="rule"
>select="document('mapping.xml')/mapping/rule[@inbound=name(current())]"/>
> <xsl:choose>
> <xsl:when test="$rule">
> <xsl:element name="{$rule/@outbound}">
> <xsl:copy-of select="@*"/>
> <xsl:apply-templates/>
> </xsl:element>
> </xsl:if>
> <xsl:otherwise>
> <!-- No mapping - copy as is -->
> <xsl:copy>
> <xsl:copy-of select="@*"/>
> <xsl:apply-templates/>
> </xsl:copy>
> <xsl:otherwise>
> </xsl:choose>
></xsl:template>
>
>[/color]

Thanks for the help so far.
I am unable to get your example to work.

No matter whay I try, I cannot get the test to return true. I cannont
find examples of the document function either.

Could you please show me a hello world example of how one would grab
values from another xml file using the document function?

Thanks,
Pint
pintihar's Avatar
Guest - n/a Posts
#6: Re: create xslt stylesheet in code

>On Thu, 04 Mar 2004 19:07:26 +0200, "Oleg Tkachenko [MVP]"[color=blue]
><oleg@NO!SPAM!PLEASEtkachenko.com> wrote:
>[color=green]
>>pintihar wrote:
>>[color=darkred]
>>> Are you suggesting in the first case, that the mapping would imposed
>>> on the writer of the inbound xml to conform to a known format?[/color]
>>
>>Nope, leave alone inbound XML, but define your own mapping XML, which
>>defines how to map inbound elements to outbound ones. Something like
>>
>><mapping>
>> <rule inbound="foo" outbound="bar"/>
>></mapping>
>>
>>Then in XSLT you can look up for mapping and output elements according
>>to rules:
>>
>><xsl:template match="*">
>> <xsl:variable name="rule"
>>select="document('mapping.xml')/mapping/rule[@inbound=name(current())]"/>
>> <xsl:choose>
>> <xsl:when test="$rule">
>> <xsl:element name="{$rule/@outbound}">
>> <xsl:copy-of select="@*"/>
>> <xsl:apply-templates/>
>> </xsl:element>
>> </xsl:if>
>> <xsl:otherwise>
>> <!-- No mapping - copy as is -->
>> <xsl:copy>
>> <xsl:copy-of select="@*"/>
>> <xsl:apply-templates/>
>> </xsl:copy>
>> <xsl:otherwise>
>> </xsl:choose>
>></xsl:template>
>>
>>[/color]
>
>Thanks for the help so far.
>I am unable to get your example to work.
>
>No matter whay I try, I cannot get the test to return true. I cannont
>find examples of the document function either.
>
>Could you please show me a hello world example of how one would grab
>values from another xml file using the document function?
>
>Thanks,
>Pint[/color]

Save ME!!!!

Well I finally determinded that my xsl works correctly when loaded in
a browser from within the xml file:
<?xml-stylesheet type="text/xsl" href="test.xsl" ?>

But, when called from within dotnet the I believe that the document
function is not working. I read about the need to use the
XmlUrlResolver object, but I can not seem to get this working.

It is hard enough to grok xsl syntax, can you explain why these files
work differenly when used in dotnet?

Thanks,
Phil

# test.xsl
<?xml version="1.0" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="*">
<xsl:variable name="rule"
select="document('mapping.xml')/mapping/rule[@inbound=name(current())]"/>
<xsl:choose>
<xsl:when test="$rule">
<xsl:element name="{$rule/@outbound}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

----

#newtest.xml
<?xml version="1.0" ?>
<?xml-stylesheet type="text/xsl" href="test.xsl" ?>
<NewDataSet>
<Lead>
<nameFirst>JACK</nameFirst>
<nameLast>Smith</nameLast>
<addrCity>Cleveland</addrCity>
<addrState>OH</addrState>
<addrStreet>200 Main</addrStreet>
<addrZIP>46140</addrZIP>
</Lead>
</NewDataSet>

----

#mapping.xml
<mapping>
<rule inbound="nameFirst" outbound="My_First_Name"/>
</mapping>

----
# dotnet code
#Attempt to call from dotnet ( xsl removed from stylsheet)

XslTransform tr = new XslTransform();
XmlUrlResolver resolver = new XmlUrlResolver();
resolver.Credentials = CredentialCache.DefaultCredentials;

tr.Load("test.xsl",resolver);
tr.Transform("newtest.xml", "TransformResult.xml", null);

----



pintihar's Avatar
Guest - n/a Posts
#7: Re: create xslt stylesheet in code

On Fri, 05 Mar 2004 02:54:18 GMT, pintihar <pintihar@earthlink.net>
wrote:
[color=blue][color=green]
>>On Thu, 04 Mar 2004 19:07:26 +0200, "Oleg Tkachenko [MVP]"
>><oleg@NO!SPAM!PLEASEtkachenko.com> wrote:
>>[color=darkred]
>>>pintihar wrote:
>>>
>>>> Are you suggesting in the first case, that the mapping would imposed
>>>> on the writer of the inbound xml to conform to a known format?
>>>
>>>Nope, leave alone inbound XML, but define your own mapping XML, which
>>>defines how to map inbound elements to outbound ones. Something like
>>>
>>><mapping>
>>> <rule inbound="foo" outbound="bar"/>
>>></mapping>
>>>
>>>Then in XSLT you can look up for mapping and output elements according
>>>to rules:
>>>
>>><xsl:template match="*">
>>> <xsl:variable name="rule"
>>>select="document('mapping.xml')/mapping/rule[@inbound=name(current())]"/>
>>> <xsl:choose>
>>> <xsl:when test="$rule">
>>> <xsl:element name="{$rule/@outbound}">
>>> <xsl:copy-of select="@*"/>
>>> <xsl:apply-templates/>
>>> </xsl:element>
>>> </xsl:if>
>>> <xsl:otherwise>
>>> <!-- No mapping - copy as is -->
>>> <xsl:copy>
>>> <xsl:copy-of select="@*"/>
>>> <xsl:apply-templates/>
>>> </xsl:copy>
>>> <xsl:otherwise>
>>> </xsl:choose>
>>></xsl:template>
>>>
>>>[/color]
>>
>>Thanks for the help so far.
>>I am unable to get your example to work.
>>
>>No matter whay I try, I cannot get the test to return true. I cannont
>>find examples of the document function either.
>>
>>Could you please show me a hello world example of how one would grab
>>values from another xml file using the document function?
>>
>>Thanks,
>>Pint[/color]
>
>Save ME!!!!
>
>Well I finally determinded that my xsl works correctly when loaded in
>a browser from within the xml file:
><?xml-stylesheet type="text/xsl" href="test.xsl" ?>
>
>But, when called from within dotnet the I believe that the document
>function is not working. I read about the need to use the
>XmlUrlResolver object, but I can not seem to get this working.
>
>It is hard enough to grok xsl syntax, can you explain why these files
>work differenly when used in dotnet?
>
>Thanks,
>Phil
>
># test.xsl
><?xml version="1.0" ?>
><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>version="1.0">
> <xsl:template match="*">
> <xsl:variable name="rule"
>select="document('mapping.xml')/mapping/rule[@inbound=name(current())]"/>
> <xsl:choose>
> <xsl:when test="$rule">
> <xsl:element name="{$rule/@outbound}">
> <xsl:copy-of select="@*"/>
> <xsl:apply-templates/>
> </xsl:element>
> </xsl:when>
> <xsl:otherwise>
> <xsl:copy>
> <xsl:copy-of select="@*"/>
> <xsl:apply-templates/>
> </xsl:copy>
> </xsl:otherwise>
> </xsl:choose>
> </xsl:template>
></xsl:stylesheet>
>
>----
>
>#newtest.xml
><?xml version="1.0" ?>
><?xml-stylesheet type="text/xsl" href="test.xsl" ?>
><NewDataSet>
> <Lead>
> <nameFirst>JACK</nameFirst>
> <nameLast>Smith</nameLast>
> <addrCity>Cleveland</addrCity>
> <addrState>OH</addrState>
> <addrStreet>200 Main</addrStreet>
> <addrZIP>46140</addrZIP>
> </Lead>
></NewDataSet>
>
>----
>
>#mapping.xml
><mapping>
> <rule inbound="nameFirst" outbound="My_First_Name"/>
></mapping>
>
>----
># dotnet code
>#Attempt to call from dotnet ( xsl removed from stylsheet)
>
>XslTransform tr = new XslTransform();
>XmlUrlResolver resolver = new XmlUrlResolver();
>resolver.Credentials = CredentialCache.DefaultCredentials;
>
>tr.Load("test.xsl",resolver);
>tr.Transform("newtest.xml", "TransformResult.xml", null);
>
>----[/color]

Woo Hoo. I got it.
The XmlUrlResolver is needed to use the 'document' function in xsl.
In my earlier posts, although I used it in the XslTransform.Load
methoh, I did not supply it to the Transform method.

Well it serves me right for trying to run before I knew how to walk.

Thanks for the assistance Oleg and Derek
-Pint
Jay B. Harlow [MVP - Outlook]'s Avatar
Jay B. Harlow [MVP - Outlook] November 12th, 2005 03:05 AM
Guest - n/a Posts
#8: Re: create xslt stylesheet in code

pintihar,[color=blue]
> Is it possible to create the stylsheet programatically?[/color]
Remember that a stylesheet is simply an XML document, so you could use any
of the objects in .NET that create XML documents to create a stylesheet. I
would probably use an XmlTextWriter. Something like:

Const ns As String = "http://www.w3.org/1999/XSL/Transform"
Const prefix As String = "xsl"

Dim writer As New Xml.XmlTextWriter("stylesheet.xslt",
System.Text.Encoding.Default)
' <?xml version="1.0" ?>
writer.WriteStartDocument()

' <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
writer.WriteStartElement(prefix, "stylesheet", ns)
' version="1.0">
writer.WriteAttributeString("version", "1.0")


' <xsl:template match="NewDataSet" >
writer.WriteStartElement(prefix, "template", ns)
writer.WriteAttributeString("match", "NewDataSet")

' <MyDataSet>
writer.WriteStartElement("MyDataSet")

' <xsl:apply-templates select="Cust" />
writer.WriteStartElement(prefix, "apply-templates", ns)
writer.WriteAttributeString("select", "Cust")
writer.WriteEndElement()

' </MyDataSet>
writer.WriteEndElement()

....

' </xsl:stylesheet>
writer.WriteEndElement()
writer.WriteEndDocument()
writer.Close()

[color=blue]
> Is this
> sensible?[/color]
Maybe. See Oleg's comments.

Hope this helps
Jay

"pintihar" <pintihar@earthlink.net> wrote in message
news:ldee405vg3eukoh18sq79cc50nb1nh38ru@4ax.com... [color=blue]
> Hi,
> As a follow on from an earlier post I have another question about
> xslt.
> Is it possible to create the stylsheet programatically? Is this
> sensible? In the first phase I needed to map element name from inbound
> xml to my internal elements to standardize disparate input.
> Now I could just create an xslt stylesheet for each possible inbound
> format and be done, but I think it would be powerful to be able store
> this mapping in a database and programatically create the stylsheet.
> This way I don't have to maintain potentially a great number of
> stylesheets. The trouble is, I can't find any example where the
> stylesheet is not Load'ed from a file.
>
> Can someone provide an example of creating the stylesheet
> programatically to pass to an XslTransform.Load method?
> Do I just write out the XML to a string?
>
> Maybe my example from before would help...
>
> <?xml version="1.0" ?>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
> version="1.0">
>
> <xsl:template match="NewDataSet" >
> <MyDataSet>
> <xsl:apply-templates select="Cust" />
> </MyDataSet>
> </xsl:template>
> <xsl:template match="Cust">
> <MyCustomer>
> <xsl:apply-templates select="nameFirst" />
> <xsl:apply-templates select="nameLast" />
> <xsl:apply-templates select="addrCity" />
> <xsl:apply-templates select="addrState" />
> <xsl:apply-templates select="addrStreet" />
> <xsl:apply-templates select="addrZIP" />
> </MyCustomer>
> </xsl:template>
>
> <xsl:template match="nameFirst">
> <MyFname>
> <xsl:value-of select="text()" />
> </MyFname>
> </xsl:template>
> <xsl:template match="nameLast">
> <MyLname>
> <xsl:value-of select="text()" />
> </MyLname>
> </xsl:template>
> <xsl:template match="addrCity">
> <MyCity>
> <xsl:value-of select="text()" />
> </MyCity>
> </xsl:template>
> <xsl:template match="addrState">
> <MyState>
> <xsl:value-of select="text()" />
> </MyState>
> </xsl:template>
> <xsl:template match="addrStreet">
> <MyStreet>
> <xsl:value-of select="text()" />
> </MyStreet>
> </xsl:template>
> <xsl:template match="addrZIP">
> <MyZIPPO>
> <xsl:value-of select="text()" />
> </MyZIPPO>
> </xsl:template>
> </xsl:stylesheet>
>
>
> Thanks in advance,
> Pint[/color]


 
Not the answer you were looking for? Post your question . . .
196,855 members ready to help you find a solution.
Join Bytes.com

What is Bytes?

We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights. Get the best answers to your questions from over 196,855 network members.
Post your question now . . .
It's fast and it's free

Popular Articles

Top Community Contributors