Sign In | Register Now About Bytes | Help | Site Map
Connecting Tech Pros Worldwide

XsltCompiledTransform question

Question posted by: =?Utf-8?B?TWFyaw==?= (Guest) on June 27th, 2008 07:20 PM
Here are three things that I thought would be equivalent but are not. Just
wondering why:

XmlElement foo = doc.CreateElement("foo");
// load it up with a body
xslt.Transform (foo, null, new XmlTextWriter(new StringWriter()));
xslt.Transform (foo.CreateNavigator(), null, new XmlTextWriter(new
StringWriter()));
xslt.Transform(new XmlNodeReader(foo), new XmlTextWriter(new StringWriter()));

Only the third one applies the transform and produces the expected output.
The first two produce nothing.

The docs say that passing in an XmlNode or navigator "usually an XmlDocument
or an XPathDocument"; it doesn't say the transform won't be applied *unless*
it's an XmlDocument.

I understand the XmlNodeReader is hiding the fact that it's starting at
something other than a document root.

I know this is an peculiar use case but was curious why the first 2 produced
nothing?

Thanks
Mark

Martin Honnen's Avatar
Martin Honnen
Guest
n/a Posts
June 27th, 2008
07:20 PM
#2

Re: XsltCompiledTransform question
Mark wrote:
Quote:
Here are three things that I thought would be equivalent but are not. Just
wondering why:
>
XmlElement foo = doc.CreateElement("foo");
// load it up with a body
xslt.Transform (foo, null, new XmlTextWriter(new StringWriter()));
xslt.Transform (foo.CreateNavigator(), null, new XmlTextWriter(new
StringWriter()));
xslt.Transform(new XmlNodeReader(foo), new XmlTextWriter(new StringWriter()));
>
Only the third one applies the transform and produces the expected output.
The first two produce nothing.
>
The docs say that passing in an XmlNode or navigator "usually an XmlDocument
or an XPathDocument"; it doesn't say the transform won't be applied *unless*
it's an XmlDocument.
>
I understand the XmlNodeReader is hiding the fact that it's starting at
something other than a document root.
>
I know this is an peculiar use case but was curious why the first 2 produced
nothing?


I am sure you can pass in an XmlElement node or an XPathNavigator
created from an XmlElement.
For instance when XSLTFile1.xslt is the identity transformation

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

then the following code

XslCompiledTransform xsltProc = new XslCompiledTransform();
xsltProc.Load(@"..\..\XSLTFile1.xslt");

XmlDocument doc = new XmlDocument();
XmlElement foo = doc.CreateElement("foo");

xsltProc.Transform(foo, null, Console.Out);
Console.WriteLine();

xsltProc.Transform(foo.CreateNavigator(), null, Console.Out);
Console.WriteLine();

outputs

<?xml version="1.0" encoding="ibm850"?><foo />
<?xml version="1.0" encoding="ibm850"?><foo />

It is not clear to me how your sample code checks any output if you
simply pass in new XmlTextWriter(new StringWriter()) as the third
argument to the Transform method. Where would you see the transformation
result in that case?

--

Martin Honnen --- MVP XML
http://JavaScript.FAQTs.com/

=?Utf-8?B?TWFyaw==?='s Avatar
=?Utf-8?B?TWFyaw==?=
Guest
n/a Posts
June 27th, 2008
07:20 PM
#3

Re: XsltCompiledTransform question
Hi Martin,

I was summarizing before; I really had
StringWriter sw = new StringWriter();
StringBuilder sb = sw.GetStringBuilder();
so I could check the output.

The issue is probably my stylesheet.
<xsl:template match="/foo">

When I pass in a dangling node, it's not matching the /. When I use an
XmlNodeReader, it can't tell the difference...

Thanks
Mark

"Martin Honnen" wrote:
Quote:
Mark wrote:
Quote:
Here are three things that I thought would be equivalent but are not. Just
wondering why:

XmlElement foo = doc.CreateElement("foo");
// load it up with a body
xslt.Transform (foo, null, new XmlTextWriter(new StringWriter()));
xslt.Transform (foo.CreateNavigator(), null, new XmlTextWriter(new
StringWriter()));
xslt.Transform(new XmlNodeReader(foo), new XmlTextWriter(new StringWriter()));

Only the third one applies the transform and produces the expected output.
The first two produce nothing.

The docs say that passing in an XmlNode or navigator "usually an XmlDocument
or an XPathDocument"; it doesn't say the transform won't be applied *unless*
it's an XmlDocument.

I understand the XmlNodeReader is hiding the fact that it's starting at
something other than a document root.

I know this is an peculiar use case but was curious why the first 2 produced
nothing?

>
I am sure you can pass in an XmlElement node or an XPathNavigator
created from an XmlElement.
For instance when XSLTFile1.xslt is the identity transformation
>
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
>
then the following code
>
XslCompiledTransform xsltProc = new XslCompiledTransform();
xsltProc.Load(@"..\..\XSLTFile1.xslt");
>
XmlDocument doc = new XmlDocument();
XmlElement foo = doc.CreateElement("foo");
>
xsltProc.Transform(foo, null, Console.Out);
Console.WriteLine();
>
xsltProc.Transform(foo.CreateNavigator(), null, Console.Out);
Console.WriteLine();
>
outputs
>
<?xml version="1.0" encoding="ibm850"?><foo />
<?xml version="1.0" encoding="ibm850"?><foo />
>
It is not clear to me how your sample code checks any output if you
simply pass in new XmlTextWriter(new StringWriter()) as the third
argument to the Transform method. Where would you see the transformation
result in that case?
>
--
>
Martin Honnen --- MVP XML
http://JavaScript.FAQTs.com/
>


Martin Honnen's Avatar
Martin Honnen
Guest
n/a Posts
June 27th, 2008
07:20 PM
#4

Re: XsltCompiledTransform question
Mark wrote:
Quote:
I was summarizing before; I really had
StringWriter sw = new StringWriter();
StringBuilder sb = sw.GetStringBuilder();
so I could check the output.
>
The issue is probably my stylesheet.
<xsl:template match="/foo">
>
When I pass in a dangling node, it's not matching the /. When I use an
XmlNodeReader, it can't tell the difference...


The XmlNodeReader reparses the DOM so it makes some sense that it
presents the foo element as a child of the root node /.
For the other two cases (passing in the sole XmlElement or the
XPathNavigator created on the sole XmlElement) the foo element has no
root so your match="/foo" does not apply.
Obviously it is an edge case but if you can change your stylesheet to
make sure you use match="foo" it should work as needed.



--

Martin Honnen --- MVP XML
http://JavaScript.FAQTs.com/

Steven Cheng [MSFT]'s Avatar
Steven Cheng [MSFT]
Guest
n/a Posts
June 27th, 2008
07:20 PM
#5

Re: XsltCompiledTransform question
Hi Mark,

I think your analysis is reasonable. The document root based path (
"/....") make a single node not be able to be resolved. While using
XmlNodeReader, it internally generate a document for the given XmlNode
which makes the difference.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
Join Bytes!.

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscript...ault.aspx#notif
ications.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.

--------------------
Quote:
>From: =?Utf-8?B?TWFyaw==?= <mmodrall@nospam.nospam>
>References: <9A461CA0-60F3-4653-BB20-065A8F554510@microsoft.com>

<elqDW5WzIHA.2408@TK2MSFTNGP04.phx.gbl>
Quote:
>Subject: Re: XsltCompiledTransform question
>Date: Fri, 13 Jun 2008 10:02:00 -0700

Quote:
>
>Hi Martin,
>
>I was summarizing before; I really had
>StringWriter sw = new StringWriter();
>StringBuilder sb = sw.GetStringBuilder();
>so I could check the output.
>
>The issue is probably my stylesheet.
<xsl:template match="/foo">
>
>When I pass in a dangling node, it's not matching the /. When I use an
>XmlNodeReader, it can't tell the difference...
>
>Thanks
>Mark
>
>"M



=?Utf-8?B?TWFyaw==?='s Avatar
=?Utf-8?B?TWFyaw==?=
Guest
n/a Posts
June 27th, 2008
07:20 PM
#6

Re: XsltCompiledTransform question
Hi Martin...

I know this is wandering a bit afield, but after this discussion I got
curious how the xpath operations on XmlNodes would respond, so I made a
little test:

XmlDocument selTest = new XmlDocument();
XmlElement selElm;
selTest.LoadXml("<foo><a><b><c><b>hi</b></c></b></a></foo>");
XmlNodeList selList = selTest.SelectNodes("//b");
selElm = selTest.DocumentElement.FirstChild as XmlElement;
selList = selElm.SelectNodes("//b");
selList = selList[0].SelectNodes("//b");
selElm = selTest.CreateElement("d");
selElm.InnerXml = "<b>in d</b>";
selList = selElm.SelectNodes("//b");

In this case, I was trying the "anywhere in tree" selection. I tried it on
the document root, a couple of elements down, and then in a dangling element.

Within the dom tree, I get the same 2 nodes no matter what node I make the
selection from.

From our prior discussion, I didn't know what to expect from the dangling
node. In the case of the dangling (unrooted) element, selecting "//b"
essentially treated the dangling node as the root and found the child.

Is this a fundamentally different case that the one we talked about before?

Thanks
Mark


Martin Honnen's Avatar
Martin Honnen
Guest
n/a Posts
June 27th, 2008
07:20 PM
#7

Re: XsltCompiledTransform question
Mark wrote:
Quote:
From our prior discussion, I didn't know what to expect from the dangling
node. In the case of the dangling (unrooted) element, selecting "//b"
essentially treated the dangling node as the root and found the child.
>
Is this a fundamentally different case that the one we talked about before?


The results astonish me.

Here is a test:

XmlDocument doc = new XmlDocument();

XmlElement foo = doc.CreateElement("foo");
foo.InnerXml = "<bar>baz</bar>";

XmlNode rootNode = foo.SelectSingleNode("/");
Console.WriteLine("rootNode.NodeType: {0}; LocalName: {1}",
rootNode.NodeType, rootNode.LocalName);

XPathNavigator fooNav = foo.CreateNavigator();
XPathNavigator rootNav = fooNav.SelectSingleNode("/");
Console.WriteLine("rootNav.NodeType: {0}; LocalName: {1}",
rootNav.NodeType, rootNav.LocalName);

Output for me with Visual Studio 2005:

rootNode.NodeType: Element; LocalName: foo
rootNav.NodeType: Element; LocalName: foo


So for the XPath API the dangling element node has itself as its root
node selected by the XPath "/". If you select "/*" then you get the
'bar' element as

XmlDocument doc = new XmlDocument();

XmlElement foo = doc.CreateElement("foo");
foo.InnerXml = "<bar>baz</bar>";

XmlNode rootElement = foo.SelectSingleNode("/*");
Console.WriteLine("rootElement.NodeType: {0}; LocalName:
{1}", rootElement.NodeType, rootElement.LocalName);

XPathNavigator fooNav = foo.CreateNavigator();
XPathNavigator rootElNav = fooNav.SelectSingleNode("/*");
Console.WriteLine("rootElNav.NodeType: {0}; LocalName:
{1}", rootElNav.NodeType, rootElNav.LocalName);

outputs

rootElement.NodeType: Element; LocalName: bar
rootElNav.NodeType: Element; LocalName: bar


That "/" selects an element node is rather odd in my view.

--

Martin Honnen --- MVP XML
http://JavaScript.FAQTs.com/

=?Utf-8?B?TWFyaw==?='s Avatar
=?Utf-8?B?TWFyaw==?=
Guest
n/a Posts
June 27th, 2008
07:20 PM
#8

Re: XsltCompiledTransform question
I was scratching my head as well. Our resident xpath/xslt guru here saw
"//b" as "descendent or self" which the XmlNode.SelectNodes() was decidedly
not doing as well. With my first doc, I got the same 2 results no matter
which node I started with, so it was running back up to the root and then
traversing down.

Given the behavior we saw in xslt with dangling nodes, I was surprised to
find the XmlNode.SelectNodes() behaving it ways that seemed quite
inconsistent with that...

Thanks
Mark


"Martin Honnen" wrote:
Quote:
Mark wrote:
>
Quote:
From our prior discussion, I didn't know what to expect from the dangling
node. In the case of the dangling (unrooted) element, selecting "//b"
essentially treated the dangling node as the root and found the child.

Is this a fundamentally different case that the one we talked about before?

>
The results astonish me.
>
Here is a test:
>
XmlDocument doc = new XmlDocument();
>
XmlElement foo = doc.CreateElement("foo");
foo.InnerXml = "<bar>baz</bar>";
>
XmlNode rootNode = foo.SelectSingleNode("/");
Console.WriteLine("rootNode.NodeType: {0}; LocalName: {1}",
rootNode.NodeType, rootNode.LocalName);
>
XPathNavigator fooNav = foo.CreateNavigator();
XPathNavigator rootNav = fooNav.SelectSingleNode("/");
Console.WriteLine("rootNav.NodeType: {0}; LocalName: {1}",
rootNav.NodeType, rootNav.LocalName);
>
Output for me with Visual Studio 2005:
>
rootNode.NodeType: Element; LocalName: foo
rootNav.NodeType: Element; LocalName: foo
>
>
So for the XPath API the dangling element node has itself as its root
node selected by the XPath "/". If you select "/*" then you get the
'bar' element as
>
XmlDocument doc = new XmlDocument();
>
XmlElement foo = doc.CreateElement("foo");
foo.InnerXml = "<bar>baz</bar>";
>
XmlNode rootElement = foo.SelectSingleNode("/*");
Console.WriteLine("rootElement.NodeType: {0}; LocalName:
{1}", rootElement.NodeType, rootElement.LocalName);
>
XPathNavigator fooNav = foo.CreateNavigator();
XPathNavigator rootElNav = fooNav.SelectSingleNode("/*");
Console.WriteLine("rootElNav.NodeType: {0}; LocalName:
{1}", rootElNav.NodeType, rootElNav.LocalName);
>
outputs
>
rootElement.NodeType: Element; LocalName: bar
rootElNav.NodeType: Element; LocalName: bar
>
>
That "/" selects an element node is rather odd in my view.
>
--
>
Martin Honnen --- MVP XML
http://JavaScript.FAQTs.com/
>


Steven Cheng [MSFT]'s Avatar
Steven Cheng [MSFT]
Guest
n/a Posts
June 27th, 2008
07:20 PM
#9

Re: XsltCompiledTransform question
Hi Mark,

I think the different behavior in XmlNode.Select with "//b" like path might
be caused by the difference context between XmlNode and XmlDocument. Since
XmlDocument has an entireo DOM context(start from root). And the "//b" like
path may also require a search from root to all descendent nodes.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
Join Bytes!.

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscript...ault.aspx#notif
ications.

==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
Quote:
>Thread-Topic: XsltCompiledTransform question
>thread-index: AcjQnqeS97g6+D1NSG+IYJh/7hksDQ==
>X-WBNR-Posting-Host: 65.55.21.8
>From: =?Utf-8?B?TWFyaw==?= <mmodrall@nospam.nospam>
>References: <9A461CA0-60F3-4653-BB20-065A8F554510@microsoft.com>

<elqDW5WzIHA.2408@TK2MSFTNGP04.phx.gbl<85E372C4-C273-4C72-
Quote:
>
>I was scratching my head as well. Our resident xpath/xslt guru here saw
>"//b" as "descendent or self" which the XmlNode.SelectNodes() was

decidedly
Quote:
>not doing as well. With my first doc, I got the same 2 results no matter
>which node I started with, so it was running back up to the root and then
>traversing down.
>
>Given the behavior we saw in xslt with dangling nodes, I was surprised to
>find the XmlNode.SelectNodes() behaving it ways that seemed quite
>inconsistent with that...
>
>Thanks
>Mark
>
>
>"Martin Honnen" wrote:
>
Quote:
>Mark wrote:
>>
Quote:
From our prior discussion, I didn't know what to expect from the

dangling
Quote:
Quote:
Quote:
node. In the case of the dangling (unrooted) element, selecting "//b"
essentially treated the dangling node as the root and found the child.
>
Is this a fundamentally different case that the one we talked about

before?
Quote:
Quote:
>>
>The results astonish me.
>>
>Here is a test:
>>
> XmlDocument doc = new XmlDocument();
>>
> XmlElement foo = doc.CreateElement("foo");
> foo.InnerXml = "<bar>baz</bar>";
>>
> XmlNode rootNode = foo.SelectSingleNode("/");
> Console.WriteLine("rootNode.NodeType: {0}; LocalName: {1}",
>rootNode.NodeType, rootNode.LocalName);
>>
> XPathNavigator fooNav = foo.CreateNavigator();
> XPathNavigator rootNav = fooNav.SelectSingleNode("/");
> Console.WriteLine("rootNav.NodeType: {0}; LocalName: {1}",
>rootNav.NodeType, rootNav.LocalName);
>>
>Output for me with Visual Studio 2005:
>>
>rootNode.NodeType: Element; LocalName: foo
>rootNav.NodeType: Element; LocalName: foo
>>
>>
>So for the XPath API the dangling element node has itself as its root
>node selected by the XPath "/". If you select "/*" then you get the
>'bar' element as
>>
> XmlDocument doc = new XmlDocument();
>>
> XmlElement foo = doc.CreateElement("foo");
> foo.InnerXml = "<bar>baz</bar>";
>>
> XmlNode rootElement = foo.SelectSingleNode("/*");
> Console.WriteLine("rootElement.NodeType: {0}; LocalName:
>{1}", rootElement.NodeType, rootElement.LocalName);
>>
> XPathNavigator fooNav = foo.CreateNavigator();
> XPathNavigator rootElNav = fooNav.SelectSingleNode("/*");
> Console.WriteLine("rootElNav.NodeType: {0}; LocalName:
>{1}", rootElNav.NodeType, rootElNav.LocalName);
>>
>outputs
>>
>rootElement.NodeType: Element; LocalName: bar
>rootElNav.NodeType: Element; LocalName: bar
>>
>>
>That "/" selects an element node is rather odd in my view.
>>
>--
>>
> Martin Honnen --- MVP XML
> http://JavaScript.FAQTs.com/
>>

>



 
Not the answer you were looking for? Post your question . . .
189,871 Experts ready to help you find a solution.
Sign up for a free account, or Login (if you're already a member).

Latest Articles: Read & Comment
  • Didn't find the answer you were looking for?
    Post Your Question
  • Top Community Contributors