Has Anyone Actually Got GetXmlNodeByXPath Working?
Just curious, as whenever I try and use it - It never ever works??? Simple example below based on the Wiki example (Still won't work?) - Here is the Xpath I want to use
System.Xml.Xsl.XslTransformException: An error occurred during a call to extension function 'GetXmlNodeByXPath'. See InnerException for a complete description of the error. ---> System.Xml.XPath.XPathException: Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function. at MS.Internal.Xml.XPath.CompiledXpathExpr.get_QueryTree() at System.Xml.XPath.XPathNavigator.Evaluate(XPathExpression expr, XPathNodeIterator context) at System.Xml.XPath.XPathNavigator.Evaluate(XPathExpression expr) at System.Xml.XPath.XPathNavigator.Select(XPathExpression expr) at System.Xml.XPath.XPathNavigator.Select(String xpath) at umbraco.library.GetXmlNodeByXPath(String xpathQuery) --- End of inner exception stack trace --- at System.Xml.Xsl.Runtime.XmlExtensionFunction.Invoke(Object extObj, Object[] args) at System.Xml.Xsl.Runtime.XmlQueryContext.InvokeXsltLateBoundFunction(String name, String namespaceUri, IList`1[] args) at (XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}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 dataSources, XsltArgumentList argumentList, XmlSequenceWriter results) at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter writer, Boolean closeWriter) at System.Xml.Xsl.XmlILCommand.Execute(IXPathNavigable contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter results) at System.Xml.Xsl.XmlILCommand.Execute(IXPathNavigable contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, TextWriter results) at System.Xml.Xsl.XslCompiledTransform.Transform(IXPathNavigable input, XsltArgumentList arguments, TextWriter results) at umbraco.macro.GetXsltTransformResult(XmlDocument macroXML, XslCompiledTransform xslt, Dictionary`2 parameters) at umbraco.presentation.umbraco.developer.Xslt.xsltVisualize.visualizeDo_Click(Object sender, EventArgs e)
Now I can get round this using a custom C# function that Doug sorted out, but I just want to know why I can't use this built in method? What am I doing wrong??
That error is because you are using a namespace-prefix/extension (i.e. umbraco.library), in the XPath query you are passing to the GetXmlNodeByXPath() method.
GetXmlNodeByXPath() doesn't load in any XSLT extensions, so you are limited to pure XPath 1.0 syntax.
You probably don't need GetXmlNodeByXPath() at all, since you could just stick with GetXmlNodeById:
Lee, sorry that it's frustrating you... it will all make sense at some point (honest, I hope).
The problem with your revised xpath is that it's got "$currentPage" in there now. Again, the GetNodeByXPath() has no context of $currentPage (same as the XSLT extensions) - so throws the error.
I do think what you are after ... and a few other people would find useful - is a node-set filter ... so you can pass in a node-set and an XPath query, and get back what you need. I think this is what Doug showed you last time - but would be good if it was available in umbraco.library.
To be honest I have been looking into that, I started to watch aarons screen casts and signed up for TekPub - Where Justin Etheridge has started a Linq series :)
I've got a yet-to-be-released upcoming version of XML Dump with a crude implementation of an 'xpath' option that uses the GetXmlNodeByXPath() function - so, yes, I have actually been able to get that darned function working :-)
The GetXmlNodeByXpath acutally runs an xpath query on the root of the umbraco xml content (umbraco.config), so you cannot pass variable name in your xpath statement, since the transformation done by GetXmlNodeByXPath has no access to the values in these variables when running the query.
So you need to output the values of your variables into the xpath string you're building, and do away with the $currentPage
In the code below I've replaced the GetXmlNodeById with the "//descendant::node[@id='1105']" which finds any descendant below the root node with id=1105, and I've concatenated the variable values into the xpath variable:
I think you're making it harder to solve the problem by using GetXmlNodeByXPath here, if you just want a node set from the xpath you were building, I think this would be simpler:
Has Anyone Actually Got GetXmlNodeByXPath Working?
Just curious, as whenever I try and use it - It never ever works??? Simple example below based on the Wiki example (Still won't work?) - Here is the Xpath I want to use
And here is how I use it (Based on this Wiki entry > http://our.umbraco.org/wiki/reference/umbracolibrary/getxmlnodebyxpath)
Error I get
Error parsing the XSLT:
System.Xml.Xsl.XslTransformException: An error occurred during a call to extension function 'GetXmlNodeByXPath'. See InnerException for a complete description of the error. ---> System.Xml.XPath.XPathException: Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function. at MS.Internal.Xml.XPath.CompiledXpathExpr.get_QueryTree() at System.Xml.XPath.XPathNavigator.Evaluate(XPathExpression expr, XPathNodeIterator context) at System.Xml.XPath.XPathNavigator.Evaluate(XPathExpression expr) at System.Xml.XPath.XPathNavigator.Select(XPathExpression expr) at System.Xml.XPath.XPathNavigator.Select(String xpath) at umbraco.library.GetXmlNodeByXPath(String xpathQuery) --- End of inner exception stack trace --- at System.Xml.Xsl.Runtime.XmlExtensionFunction.Invoke(Object extObj, Object[] args) at System.Xml.Xsl.Runtime.XmlQueryContext.InvokeXsltLateBoundFunction(String name, String namespaceUri, IList`1[] args) at (XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}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 dataSources, XsltArgumentList argumentList, XmlSequenceWriter results) at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter writer, Boolean closeWriter) at System.Xml.Xsl.XmlILCommand.Execute(IXPathNavigable contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter results) at System.Xml.Xsl.XmlILCommand.Execute(IXPathNavigable contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, TextWriter results) at System.Xml.Xsl.XslCompiledTransform.Transform(IXPathNavigable input, XsltArgumentList arguments, TextWriter results) at umbraco.macro.GetXsltTransformResult(XmlDocument macroXML, XslCompiledTransform xslt, Dictionary`2 parameters) at umbraco.presentation.umbraco.developer.Xslt.xsltVisualize.visualizeDo_Click(Object sender, EventArgs e)
Now I can get round this using a custom C# function that Doug sorted out, but I just want to know why I can't use this built in method? What am I doing wrong??
Hi Lee,
That error is because you are using a namespace-prefix/extension (i.e. umbraco.library), in the XPath query you are passing to the GetXmlNodeByXPath() method.
GetXmlNodeByXPath() doesn't load in any XSLT extensions, so you are limited to pure XPath 1.0 syntax.
You probably don't need GetXmlNodeByXPath() at all, since you could just stick with GetXmlNodeById:
Hope that helps? (a little)
Cheers, Lee.
Ahhhh I'm with you! Awesome I'll give it a crack now.. Yet another Guinness I owe you ;)
Just to go back to this, I shouldn't have marked it as solved - I meant to give Lee a thumbs up (But you can't remove it once its been marked!!)
Anyway... This GetXmlNodeById just doesn't work! I have changed it to full xpath like so
<xsl:variable name="myxpath"> <xsl:choose> <xsl:when test="string($thesearch) != ''"> <xsl:text>$currentPage/ancestor-or-self::node/descendant::node [@nodeTypeAlias = $documentTypeAlias and contains(./@nodeName, $thesearch)]</xsl:text> </xsl:when> <xsl:otherwise> <xsl:text>$currentPage/ancestor-or-self::node/descendant::node [@nodeTypeAlias = $documentTypeAlias]</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:for-each select="umbraco.library:GetXmlNodeByXPath($myxpath)">
Still this doesn't work, get the following error??? Man how anyone can say using XSLT is better than .NET I'll never know :(
Damn that should read
This GetXmlNodeByXPath just doesn't work! I have changed it to full xpath like so (No edit button lol)
Sorry... The error is exactly the same as the top one :(
I haven't used it before, but I have a wild guess:
contains(./@nodeName, $thesearch)] --> that's a function right?
Lee, sorry that it's frustrating you... it will all make sense at some point (honest, I hope).
The problem with your revised xpath is that it's got "$currentPage" in there now. Again, the GetNodeByXPath() has no context of $currentPage (same as the XSLT extensions) - so throws the error.
I do think what you are after ... and a few other people would find useful - is a node-set filter ... so you can pass in a node-set and an XPath query, and get back what you need. I think this is what Doug showed you last time - but would be good if it was available in umbraco.library.
Cheers, (the other) Lee
Hey Lee - Don't apologise dude, you have been a great help :)
I did blog the function Doug and his wife sorted for me (http://www.blogfodder.co.uk/post/Building-Up-A-String-XPath-Statement-In-XSLT.aspx) but as that function was there I was determined to get the bloody thing to work for my own sanity! (But failed so far ... lol)
I have left it for the mo, and will attack it tomorrow with a fresh head :)
Just make life easier, use LINQ!
Hehe, sorry, I'm a .NET / LINQ addict :P
To be honest I have been looking into that, I started to watch aarons screen casts and signed up for TekPub - Where Justin Etheridge has started a Linq series :)
Hi Lee,
I've got a yet-to-be-released upcoming version of XML Dump with a crude implementation of an 'xpath' option that uses the GetXmlNodeByXPath() function - so, yes, I have actually been able to get that darned function working :-)
/Chriztian
Hi Lee
The GetXmlNodeByXpath acutally runs an xpath query on the root of the umbraco xml content (umbraco.config), so you cannot pass variable name in your xpath statement, since the transformation done by GetXmlNodeByXPath has no access to the values in these variables when running the query.
So you need to output the values of your variables into the xpath string you're building, and do away with the $currentPage
In the code below I've replaced the GetXmlNodeById with the "//descendant::node[@id='1105']" which finds any descendant below the root node with id=1105, and I've concatenated the variable values into the xpath variable:
That should do the trick, but you might want to check that your xpath statement actually is correct, by outputting it to your code with a
Before inserting it into the GetXmlNodeByXPath method.
Regards
Jesper Hauge
Hi again
Just had to append this:
I think you're making it harder to solve the problem by using GetXmlNodeByXPath here, if you just want a node set from the xpath you were building, I think this would be simpler:
Regards
Jesper Hauge
is working on a reply...