fork download
  1. using System;
  2. using System.Xml;
  3. using System.Xml.Xsl;
  4. using System.Xml.XPath;
  5.  
  6. using System.Collections.Generic;
  7. using System.IO;
  8.  
  9. public class Test
  10. {
  11. public static void Main()
  12. {
  13. var s = @"
  14. <Root>
  15. <Start refId = ""5""/>
  16. <Start refId = ""6""/>
  17. <Item id = ""5""/>
  18. <Item id = ""6""/>
  19. </Root>
  20. ";
  21.  
  22. var doc = new XmlDocument();
  23. using (var sr = new StringReader(s))
  24. {
  25. doc.Load(sr);
  26. }
  27.  
  28. VariableContext vc = new VariableContext();
  29. XmlNode nodea = doc.SelectSingleNode("Root/Start[1]");
  30. vc.SetValue("a", nodea);
  31. XmlNodeList selected = doc.SelectNodes("/Root/Item[@id = $a/@refId]", vc);
  32. PrintNodeList(selected);
  33.  
  34. // There isn't a need to use separate VariableContexts, but just keeping
  35. // everything separate here
  36. VariableContext vc2 = new VariableContext();
  37. XmlNode nodea2 = doc.SelectSingleNode("Root/Start[1]");
  38. vc2.SetCurrentNode(nodea2);
  39. XmlNodeList selected2 = doc.SelectNodes("/Root/Item[@id = current()/@refId]", vc2);
  40. PrintNodeList(selected2);
  41. }
  42.  
  43. static void PrintNodeList(XmlNodeList list)
  44. {
  45. Console.WriteLine("Node list contents.");
  46. foreach (XmlNode node in list)
  47. {
  48. Console.WriteLine("\t" + node.OuterXml.Replace("\\s", ""));
  49.  
  50. }
  51. Console.WriteLine();
  52. }
  53. }
  54.  
  55. public class VariableContext : XsltContext
  56. {
  57. IXPathNavigable CurrentNode;
  58.  
  59. Dictionary<string, object> Values = new Dictionary<string, object>();
  60. public void SetValue(string name, object value)
  61. {
  62. Values[name] = value;
  63. }
  64. public void SetCurrentNode(IXPathNavigable currentNode)
  65. {
  66. CurrentNode = currentNode;
  67. }
  68.  
  69. public override int CompareDocument(string baseUri, string nextbaseUri)
  70. {
  71. throw new NotImplementedException();
  72. }
  73.  
  74. public override bool PreserveWhitespace(System.Xml.XPath.XPathNavigator node)
  75. {
  76. return false;
  77. }
  78.  
  79. public override IXsltContextFunction ResolveFunction(string prefix, string name, System.Xml.XPath.XPathResultType[] ArgTypes)
  80. {
  81. if (name.Equals("current"))
  82. {
  83. return new CurrentFunction(CurrentNode);
  84. }
  85. throw new NotImplementedException();
  86. }
  87.  
  88. public override IXsltContextVariable ResolveVariable(string prefix, string name)
  89. {
  90. object value;
  91. if (Values.TryGetValue(name, out value))
  92. {
  93. return new ContextVariable(name, value);
  94. }
  95. throw new ApplicationException("Unknown variable: " + name);
  96. }
  97.  
  98. public override bool Whitespace
  99. {
  100. get { return false; }
  101. }
  102. }
  103.  
  104. public class ContextVariable : IXsltContextVariable
  105. {
  106. private string m_name;
  107. private object m_parameter;
  108.  
  109. public ContextVariable(string name, object parameter)
  110. {
  111. m_name = name;
  112. m_parameter = parameter;
  113.  
  114. IXPathNavigable navigable = m_parameter as IXPathNavigable;
  115. if (navigable != null)
  116. {
  117. m_parameter = navigable.CreateNavigator().Select(".");
  118. }
  119. }
  120.  
  121. #region IXsltContextVariable Members
  122.  
  123. public object Evaluate(XsltContext xsltContext)
  124. {
  125. return m_parameter;
  126. }
  127.  
  128. public bool IsLocal
  129. {
  130. get { return true; }
  131. }
  132.  
  133. public bool IsParam
  134. {
  135. get { return true; }
  136. }
  137.  
  138. public XPathResultType VariableType
  139. {
  140. get
  141. {
  142. return XPathResultType.Any;
  143. }
  144. }
  145.  
  146. #endregion
  147. }
  148.  
  149. public class CurrentFunction : IXsltContextFunction
  150. {
  151. private XPathNodeIterator CurrentNodeIterator;
  152. internal CurrentFunction(IXPathNavigable currentNode)
  153. {
  154. if (currentNode != null)
  155. {
  156. CurrentNodeIterator = currentNode.CreateNavigator().Select(".");
  157. }
  158. }
  159.  
  160. public XPathResultType[] ArgTypes
  161. {
  162. get { return new XPathResultType[0]; }
  163. }
  164.  
  165. public object Invoke(XsltContext xsltContext, object[] args,
  166. XPathNavigator docContext)
  167. {
  168. if (CurrentNodeIterator == null)
  169. {
  170. throw new ApplicationException("Current node is not set.");
  171. }
  172. return CurrentNodeIterator;
  173. }
  174.  
  175. public int Maxargs
  176. {
  177. get { return 0; }
  178. }
  179.  
  180. public int Minargs
  181. {
  182. get { return 0; }
  183. }
  184.  
  185. public XPathResultType ReturnType
  186. {
  187. get { return XPathResultType.NodeSet; }
  188. }
  189. }
  190.  
Success #stdin #stdout 0.15s 34720KB
stdin
Standard input is empty
stdout
Node list contents.
	<Item id="5" />

Node list contents.
	<Item id="5" />