Ureader.com  
Microsoft software help and Community
   home   |   control panel login   |   archive   |  
 
XML
data.xmlanalysis
mappoint.webservice
msf
msxml-webrelease
netmyservices.sdk
passport.sdk
soap
soapsdk
uddi.general
uddi.programming
uddi.specification
xml
xmlsqlwebrelease
xsl
  
 
date: Fri, 1 Aug 2008 14:31:01 -0700,    group: microsoft.public.xsl        back       


Passing an XPathNavigator to a custum function.   
I have the following C# code that illustrates the problem I am having:

        static void TestCount(int id, IEnumerable<string> messages, 
IEnumerable<string> skus)
        {
            XslCompiledTransform xsltProc = new XslCompiledTransform();
            XsltSettings xsltSettings = new XsltSettings(false, true);
            xsltProc.Load(@"..\..\TestStyleSheet.xsl", xsltSettings, null);

            XmlDocument messageDoc = MakeMessageDoc(messages);
            XmlDocument skuDoc = MakeSkuDoc(skus);

            XsltArgumentList args = new XsltArgumentList();
            args.AddParam("DocumentTransactionId", string.Empty, id);
            args.AddParam("IdenticalList", string.Empty, skuDoc);
            args.AddParam("MessageTestList", string.Empty, messageDoc);
            args.AddParam("CatalogConnectionString", string.Empty, "test 
connection");

            
xsltProc.Transform(XmlReader.Create(File.OpenRead(@"..\..\XmlSent.xml")), 
args, Console.Out);
            Console.WriteLine();
            Console.WriteLine("Number of item elements: {0}.",
skuDoc.SelectNodes("/root/list/sku").Count);
            Console.WriteLine();
            Console.WriteLine();
        }

        static XmlDocument MakeSkuDoc(IEnumerable<string> items)
        {
            XmlDocument paramDoc = new XmlDocument();
            using (XmlWriter writer =
paramDoc.CreateNavigator().AppendChild())
            {
                writer.WriteStartElement("root");
                writer.WriteStartElement("list");
                foreach (string item in items)
                {
                    writer.WriteElementString("sku", item);
                }
                writer.WriteEndElement();
                writer.WriteEndElement();
            }
            return paramDoc;
        }
        static XmlDocument MakeMessageDoc(IEnumerable<string> items)
        {
            XmlDocument messageDoc = new XmlDocument();
            using (XmlWriter writer =
messageDoc.CreateNavigator().AppendChild())
            {
                writer.WriteStartElement("root");
                writer.WriteStartElement("list");
                foreach (string item in items)
                {
                    writer.WriteElementString("item", item);
                }
                writer.WriteEndElement();
                writer.WriteEndElement();
            }
            return messageDoc;
        }

        static void Main(string[] args)
        {
            TestCount(10, new string[] { "1", "2", "3", "4", "5" }, new 
string[] { "21200-140319", "11442-114976", "19930" });
            TestCount(30, new string[] { "1" }, new string[] { 
"21200-140319", "11442-114976", "19930" });
            TestCount(40, new string[] { }, new string[] { });
        }


And the stylesheet:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:bsi="http://BuySeasons/SqlXslFunctions">
	<msxsl:script language="C#" implements-prefix="bsi">
		public bool MerchandisedProduct(string connectionString, XPathNavigator nav)
		{
		return false;
		}
	</msxsl:script>
	<xsl:param name="MessageTestList"/>
	<xsl:param name="DocumentTransactionId"/>
	<xsl:param name="IdenticalList"/>
	<xsl:param name="CatalogConnectionString"/>
	<xsl:template match="/">
		<HTML>
			<BODY>
				<h3>
					We cannot recognize your child SKU Document Transaction Id - 
<xsl:value-of select="$DocumentTransactionId"/>
				</h3>
				<br/>
				<br/>
				<h4>
					Identical Errors - <xsl:value-of 
select="count(/AmazonEnvelope/Message[(MessageID = 
$MessageTestList/root/list/item) and (Relationship/Relation/SKU = 
$IdenticalList/root/list/sku)])"/>
					Unmerchandised Errors - <xsl:value-of 
select="count(/AmazonEnvelope/Message[(MessageID = 
$MessageTestList/root/list/item) and 
not(bsi:MerchandisedProduct($CatalogConnectionString,Relationship/Relation/SKU))])"/>
				</h4>
			</BODY>
		</HTML>
	</xsl:template>

</xsl:stylesheet>

and the first few lines of the XML that I am using:


<AmazonEnvelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xsi:noNamespaceSchemaLocation="amzn-envelope.xsd">
  <Header>
    <DocumentVersion>1.01</DocumentVersion>
    <MerchantIdentifier>M_BUYCOSTUME_330363</MerchantIdentifier>
  </Header>
  <MessageType>Relationship</MessageType>
  <PurgeAndReplace>false</PurgeAndReplace>
  <Message>
    <MessageID>1</MessageID>
    <OperationType>Update</OperationType>
    <Relationship>
      <ParentSKU>10041-109342</ParentSKU>
      <Relation>
        <SKU>21200-140319</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>18636-133654</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>19316-134062</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>31053-144544</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>31991-146377</SKU>
        <Type>Accessory</Type>
      </Relation>
    </Relationship>
  </Message>
  <Message>
    <MessageID>2</MessageID>
    <OperationType>Update</OperationType>
    <Relationship>
      <ParentSKU>10052-112512</ParentSKU>
      <Relation>
        <SKU>11442-114976</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>12297-113846</SKU>
        <Type>Accessory</Type>
      </Relation>
    </Relationship>
  </Message>
  <Message>
    <MessageID>3</MessageID>
    <OperationType>Update</OperationType>
    <Relationship>
      <ParentSKU>10074-112504</ParentSKU>
      <Relation>
        <SKU>19930</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>19899</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>17392-125713</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>31052-144543</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>33572</SKU>
        <Type>Accessory</Type>
      </Relation>
    </Relationship>
  </Message>
  <Message>
    <MessageID>4</MessageID>
    <OperationType>Update</OperationType>
    <Relationship>
      <ParentSKU>10087</ParentSKU>
      <Relation>
        <SKU>21267-140386</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>20347-138059</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>11555</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>10330-111730</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>31061</SKU>
        <Type>Accessory</Type>
      </Relation>
    </Relationship>
  </Message>
  <Message>
    <MessageID>5</MessageID>
    <OperationType>Update</OperationType>
    <Relationship>
      <ParentSKU>10090</ParentSKU>
      <Relation>
        <SKU>1787-102265</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>31300-145019</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>31301-145020</SKU>
        <Type>Accessory</Type>
      </Relation>
    </Relationship>
  </Message>
  <Message>
    <MessageID>6</MessageID>
    <OperationType>Update</OperationType>
    <Relationship>
      <ParentSKU>10102</ParentSKU>
      <Relation>
        <SKU>27405-143173</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>1424-102268</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>1787-102265</SKU>
        <Type>Accessory</Type>
      </Relation>
    </Relationship>
  </Message>
  <Message>
    <MessageID>7</MessageID>
    <OperationType>Update</OperationType>
    <Relationship>
      <ParentSKU>10114-112615</ParentSKU>
      <Relation>
        <SKU>21515</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>21683</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>19230-133916</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>11575-114873</SKU>
        <Type>Accessory</Type>
      </Relation>
      <Relation>
        <SKU>6190</SKU>
        <Type>Accessory</Type>
      </Relation>
    </Relationship>
  </Message>
</AmazonEnvelope>

Running the code gives me an XslException:

System.Xml.Xsl.XslTransformException: Cannot convert a node-set which 
contains z
ero nodes or more than one node to a single node.
   at System.Xml.Xsl.Runtime.XsltConvert.ToNode(IList`1 listItems)
   at <xsl:template match="/">(XmlQueryRuntime 
{urn:schemas-microsoft-com:xslt-d
ebug}runtime, XPathNavigator {urn:schemas-microsoft-com:xslt-debug}current)
   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 da
taSources, XsltArgumentList argumentList, XmlSequenceWriter results)
   at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, 
XmlResolver da
taSources, XsltArgumentList argumentList, XmlWriter writer, Boolean 
closeWriter)

   at System.Xml.Xsl.XmlILCommand.Execute(XmlReader contextDocument, 
XmlResolver
 dataSources, XsltArgumentList argumentList, TextWriter results)
   at System.Xml.Xsl.XslCompiledTransform.Transform(XmlReader input, 
XsltArgumen
tList arguments, TextWriter results)
   at TestSyleSheet.Program.TestCount(Int32 id, IEnumerable`1 messages, 
IEnumera
ble`1 skus) in 
C:\Projects\BuySeasonsIT\Source\Brain\Trunk\BuyseasonsServices\Te
stSyleSheet\Program.cs:line 29
   at TestSyleSheet.Program.Main(String[] args) in 
C:\Projects\BuySeasonsIT\Sour
ce\Brain\Trunk\BuyseasonsServices\TestSyleSheet\Program.cs:line 76

I was wondering if this is a limitation of Xslt or if there was a work around?

Thank you.

Kevin
date: Fri, 1 Aug 2008 14:31:01 -0700   author:   Kevin Burton

Re: Passing an XPathNavigator to a custum function.   
Kevin Burton wrote:

> 	<msxsl:script language="C#" implements-prefix="bsi">
> 		public bool MerchandisedProduct(string connectionString, XPathNavigator nav)
> 		{
> 		return false;
> 		}
> 	</msxsl:script>

> not(bsi:MerchandisedProduct($CatalogConnectionString,Relationship/Relation/SKU))])"/>

> I was wondering if this is a limitation of Xslt or if there was a work around?

I think the problem is the extension function, you have defined the 
second argument as an XPathNavigator but then you pass in a node-set 
with several arguments (Relationship/Relation/SKU), that does not work. 
You need to use an XPathNodeIterator as the argument type if you want to 
pass in a node-set with several nodes. If you want to use the type 
XPathNavigator then you need to make sure you pass in a single node.


-- 

	Martin Honnen --- MVP XML
	http://JavaScript.FAQTs.com/
date: Sat, 02 Aug 2008 14:15:09 +0200   author:   Martin Honnen

Re: Passing an XPathNavigator to a custum function.   
Not to be argumentative but mearly trying to understand. Besides, whatever 
works, right?

There is some sample code under the XPathNavigator that shows recursive 
calls to XPathNavigator using MoveNext() starting out with 
MoveToFirstChild(). This would suggest that XPathNavigator handles more than 
one node. If not then what is the difference between XPathNavigator and just 
XmlNode?

Thanks again.

"Martin Honnen" wrote:

> Kevin Burton wrote:
> 
> > 	<msxsl:script language="C#" implements-prefix="bsi">
> > 		public bool MerchandisedProduct(string connectionString, XPathNavigator nav)
> > 		{
> > 		return false;
> > 		}
> > 	</msxsl:script>
> 
> > not(bsi:MerchandisedProduct($CatalogConnectionString,Relationship/Relation/SKU))])"/>
> 
> > I was wondering if this is a limitation of Xslt or if there was a work around?
> 
> I think the problem is the extension function, you have defined the 
> second argument as an XPathNavigator but then you pass in a node-set 
> with several arguments (Relationship/Relation/SKU), that does not work. 
> You need to use an XPathNodeIterator as the argument type if you want to 
> pass in a node-set with several nodes. If you want to use the type 
> XPathNavigator then you need to make sure you pass in a single node.
> 
> 
> -- 
> 
> 	Martin Honnen --- MVP XML
> 	http://JavaScript.FAQTs.com/
>
date: Sat, 2 Aug 2008 10:39:00 -0700   author:   Kevin Burton

Re: Passing an XPathNavigator to a custum function.   
Kevin Burton wrote:
> Not to be argumentative but mearly trying to understand. Besides, whatever 
> works, right?
> 
> There is some sample code under the XPathNavigator that shows recursive 
> calls to XPathNavigator using MoveNext() starting out with 
> MoveToFirstChild(). This would suggest that XPathNavigator handles more than 
> one node. If not then what is the difference between XPathNavigator and just 
> XmlNode?

MoveNext is not a method of XPathNavigator. MoveToFirstChild is one.
I am not sure which sample code you refer to, either post it or post a 
URL to it.
As for passing objects to extension functions in XSLT stylesheets, see 
http://msdn.microsoft.com/en-us/library/wxaw5z5e(VS.80).aspx, it lists 
XPathNodeIterator as a class corresponding to a node set.

As for the difference between XPathNavigator and XmlNode, XmlNode and 
its subclasses are the DOM implementation in the .NET framework while 
XPathNavigator is an abstract class that provides a model for XPath 
based navigation. There are concrete implementations of that, one for 
the DOM model (XmlNode/XmlDocument/XmlElement and so on), one for 
XPathDocument.





-- 

	Martin Honnen --- MVP XML
	http://JavaScript.FAQTs.com/
date: Sun, 03 Aug 2008 13:48:49 +0200   author:   Martin Honnen

Re: Passing an XPathNavigator to a custum function.   
I am sorry I meant to type MoveToNext. The recursive function is listed in 
the documetation for that method.

Kevin

"Martin Honnen" wrote:

> Kevin Burton wrote:
> > Not to be argumentative but mearly trying to understand. Besides, whatever 
> > works, right?
> > 
> > There is some sample code under the XPathNavigator that shows recursive 
> > calls to XPathNavigator using MoveNext() starting out with 
> > MoveToFirstChild(). This would suggest that XPathNavigator handles more than 
> > one node. If not then what is the difference between XPathNavigator and just 
> > XmlNode?
> 
> MoveNext is not a method of XPathNavigator. MoveToFirstChild is one.
> I am not sure which sample code you refer to, either post it or post a 
> URL to it.
> As for passing objects to extension functions in XSLT stylesheets, see 
> http://msdn.microsoft.com/en-us/library/wxaw5z5e(VS.80).aspx, it lists 
> XPathNodeIterator as a class corresponding to a node set.
> 
> As for the difference between XPathNavigator and XmlNode, XmlNode and 
> its subclasses are the DOM implementation in the .NET framework while 
> XPathNavigator is an abstract class that provides a model for XPath 
> based navigation. There are concrete implementations of that, one for 
> the DOM model (XmlNode/XmlDocument/XmlElement and so on), one for 
> XPathDocument.
> 
> 
> 
> 
> 
> -- 
> 
> 	Martin Honnen --- MVP XML
> 	http://JavaScript.FAQTs.com/
>
date: Sun, 3 Aug 2008 08:42:01 -0700   author:   Kevin Burton

Re: Passing an XPathNavigator to a custum function.   
Kevin Burton wrote:
> I am sorry I meant to type MoveToNext. The recursive function is listed in 
> the documetation for that method.

XPathNavigator allows you to navigate the XPath data model, that is 
true. So you can navigate to a child (navigator.MoveToFirstChild()), you 
can navigate to the next sibling (navigator.MoveToNext()), that is all 
possible, but at any time the navigator is positioned on exactly one 
node, not on a node-set with several nodes. If you are dealing with 
node-sets with (potentially) several nodes then XPathNodeIterator is 
returned, for instance if you use the Select method of XPathNavigator 
http://msdn.microsoft.com/en-us/library/0ea193ac.aspx or the 
SelectChildren method http://msdn.microsoft.com/en-us/library/d4aaawwa.aspx.

So I don't see how that example contradicts my suggestion to use 
XPathNodeIterator as the argument type for your extension function you 
call with a node-set of more than one node in your stylesheet.

As long as you know you pass in a node-set with a single node you can 
use XPathNavigator but otherwise you need XPathNodeIterator. That is the 
way the API is designed.


What happened to your count problem, is that solved?

-- 

	Martin Honnen --- MVP XML
	http://JavaScript.FAQTs.com/
date: Sun, 03 Aug 2008 19:23:43 +0200   author:   Martin Honnen

Re: Passing an XPathNavigator to a custum function.   
Thank you. I think I understand the difference. 

The count() problem I think is related to this issue. It seems that when I 
have XPath expression like:

abc[A= "x"]/d/e[customFunction(B)]

this is "countable" but a/b/c[A="X" and customFuction(d/e/B)] is not. I 
don't have any specific detail right now but knowing this seems to help the 
situation.

Thanks again.

Kevin

"Martin Honnen" wrote:

> Kevin Burton wrote:
> > I am sorry I meant to type MoveToNext. The recursive function is listed in 
> > the documetation for that method.
> 
> XPathNavigator allows you to navigate the XPath data model, that is 
> true. So you can navigate to a child (navigator.MoveToFirstChild()), you 
> can navigate to the next sibling (navigator.MoveToNext()), that is all 
> possible, but at any time the navigator is positioned on exactly one 
> node, not on a node-set with several nodes. If you are dealing with 
> node-sets with (potentially) several nodes then XPathNodeIterator is 
> returned, for instance if you use the Select method of XPathNavigator 
> http://msdn.microsoft.com/en-us/library/0ea193ac.aspx or the 
> SelectChildren method http://msdn.microsoft.com/en-us/library/d4aaawwa.aspx.
> 
> So I don't see how that example contradicts my suggestion to use 
> XPathNodeIterator as the argument type for your extension function you 
> call with a node-set of more than one node in your stylesheet.
> 
> As long as you know you pass in a node-set with a single node you can 
> use XPathNavigator but otherwise you need XPathNodeIterator. That is the 
> way the API is designed.
> 
> 
> What happened to your count problem, is that solved?
> 
> -- 
> 
> 	Martin Honnen --- MVP XML
> 	http://JavaScript.FAQTs.com/
>
date: Sun, 3 Aug 2008 13:22:01 -0700   author:   Kevin Burton

Google
 
Web ureader.com


    COPYRIGHT 2007, YARDI TECHNOLOGY LIMITED, ALL RIGHT RESERVE  |   contact us