468,168 Members | 1,494 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,168 developers. It's quick & easy.

create xslt stylesheet in code

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
Nov 12 '05 #1
7 4932
pintihar wrote:
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.


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
Nov 12 '05 #2
>> 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.


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).


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
Nov 12 '05 #3
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>

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


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
Nov 12 '05 #4
On Thu, 04 Mar 2004 19:07:26 +0200, "Oleg Tkachenko [MVP]"
<oleg@NO!SPAM!PLEASEtkachenko.com> wrote:
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>


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
Nov 12 '05 #5
>On Thu, 04 Mar 2004 19:07:26 +0200, "Oleg Tkachenko [MVP]"
<oleg@NO!SPAM!PLEASEtkachenko.com> wrote:
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>


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


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);

----

Nov 12 '05 #6
On Fri, 05 Mar 2004 02:54:18 GMT, pintihar <pi******@earthlink.net>
wrote:
On Thu, 04 Mar 2004 19:07:26 +0200, "Oleg Tkachenko [MVP]"
<oleg@NO!SPAM!PLEASEtkachenko.com> wrote:
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>


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


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);

----


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
Nov 12 '05 #7
pintihar,
Is it possible to create the stylsheet programatically? 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()

Is this
sensible? Maybe. See Oleg's comments.

Hope this helps
Jay

"pintihar" <pi******@earthlink.net> wrote in message
news:ld********************************@4ax.com... 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

Nov 12 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by Doug Farrell | last post: by
6 posts views Thread by Pete | last post: by
3 posts views Thread by IMS.Rushikesh | last post: by
1 post views Thread by gcdp | last post: by
reply views Thread by kamranasdasdas | last post: by
reply views Thread by gcreed | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.