Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Okay I was entertained by this so I hacked some code together. It isn't pretty and only really supports this one use case but I think it does the job you're looking for and acts as a decent platform to start from. I haven't tested it that thoroughly either. Finally you'll need to modify the code to get it to return the contents (see the method called Output()).</p> <p>Here is the code:</p> <pre><code>using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Xml; namespace XPathInCE { class Program { static void Main(string[] args) { try { if (args.Length != 2) { ShowUsage(); } else { Extract(args[0], args[1]); } } catch (Exception ex) { Console.WriteLine("{0} was thrown", ex.GetType()); Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } Console.WriteLine("Press ENTER to exit"); Console.ReadLine(); } private static void Extract(string filePath, string queryString) { if (!File.Exists(filePath)) { Console.WriteLine("File not found! Path: {0}", filePath); return; } XmlReaderSettings settings = new XmlReaderSettings { IgnoreComments = true, IgnoreWhitespace = true }; using (XmlReader reader = XmlReader.Create(filePath, settings)) { XPathQuery query = new XPathQuery(queryString); query.Find(reader); } } static void ShowUsage() { Console.WriteLine("No file specified or incorrect number of parameters"); Console.WriteLine("Args must be: Filename XPath"); Console.WriteLine(); Console.WriteLine("Sample usage:"); Console.WriteLine("XPathInCE someXmlFile.xml ConfigurationRelease/Profiles/Profile[Name='MyProfileName']/Screens/Screen[Id='MyScreenId']/Settings/Setting[Name='MySettingName']"); } class XPathQuery { private readonly LinkedList&lt;ElementOfInterest&gt; list = new LinkedList&lt;ElementOfInterest&gt;(); private LinkedListNode&lt;ElementOfInterest&gt; currentNode; internal XPathQuery(string query) { Parse(query); currentNode = list.First; } internal void Find(XmlReader reader) { bool skip = false; while (true) { if (skip) { reader.Skip(); skip = false; } else { if (!reader.Read()) { break; } } if (reader.NodeType == XmlNodeType.EndElement &amp;&amp; String.Compare(reader.Name, currentNode.Previous.Value.ElementName, StringComparison.CurrentCultureIgnoreCase) == 0) { currentNode = currentNode.Previous ?? currentNode; continue; } if (reader.NodeType == XmlNodeType.Element) { string currentElementName = reader.Name; Console.WriteLine("Considering element: {0}", reader.Name); if (String.Compare(reader.Name, currentNode.Value.ElementName, StringComparison.CurrentCultureIgnoreCase) != 0) { // don't want Console.WriteLine("Skipping"); skip = true; continue; } if (!FindAttributes(reader)) { // don't want Console.WriteLine("Skipping"); skip = true; continue; } // is there more? if (currentNode.Next != null) { currentNode = currentNode.Next; continue; } // we're at the end, this is a match! :D Console.WriteLine("XPath match found!"); Output(reader, currentElementName); } } } private bool FindAttributes(XmlReader reader) { foreach (AttributeOfInterest attributeOfInterest in currentNode.Value.Attributes) { if (String.Compare(reader.GetAttribute(attributeOfInterest.Name), attributeOfInterest.Value, StringComparison.CurrentCultureIgnoreCase) != 0) { return false; } } return true; } private static void Output(XmlReader reader, string name) { while (reader.Read()) { // break condition if (reader.NodeType == XmlNodeType.EndElement &amp;&amp; String.Compare(reader.Name, name, StringComparison.CurrentCultureIgnoreCase) == 0) { return; } if (reader.NodeType == XmlNodeType.Element) { Console.WriteLine("Element {0}", reader.Name); Console.WriteLine("Attributes"); for (int i = 0; i &lt; reader.AttributeCount; i++) { reader.MoveToAttribute(i); Console.WriteLine("Attribute: {0} Value: {1}", reader.Name, reader.Value); } } if (reader.NodeType == XmlNodeType.Text) { Console.WriteLine("Element value: {0}", reader.Value); } } } private void Parse(string query) { IList&lt;string&gt; elements = query.Split('/'); foreach (string element in elements) { ElementOfInterest interestingElement = null; string elementName = element; int attributeQueryStartIndex = element.IndexOf('['); if (attributeQueryStartIndex != -1) { int attributeQueryEndIndex = element.IndexOf(']'); if (attributeQueryEndIndex == -1) { throw new ArgumentException(String.Format("Argument: {0} has a [ without a corresponding ]", query)); } elementName = elementName.Substring(0, attributeQueryStartIndex); string attributeQuery = element.Substring(attributeQueryStartIndex + 1, (attributeQueryEndIndex - attributeQueryStartIndex) - 2); string[] keyValPair = attributeQuery.Split('='); if (keyValPair.Length != 2) { throw new ArgumentException(String.Format("Argument: {0} has an attribute query that either has too many or insufficient = marks. We currently only support one", query)); } interestingElement = new ElementOfInterest(elementName); interestingElement.Add(new AttributeOfInterest(keyValPair[0].Trim().Replace("'", ""), keyValPair[1].Trim().Replace("'", ""))); } else { interestingElement = new ElementOfInterest(elementName); } list.AddLast(interestingElement); } } class ElementOfInterest { private readonly string elementName; private readonly List&lt;AttributeOfInterest&gt; attributes = new List&lt;AttributeOfInterest&gt;(); public ElementOfInterest(string elementName) { this.elementName = elementName; } public string ElementName { get { return elementName; } } public List&lt;AttributeOfInterest&gt; Attributes { get { return attributes; } } public void Add(AttributeOfInterest attribute) { Attributes.Add(attribute); } } class AttributeOfInterest { private readonly string name; private readonly string value; public AttributeOfInterest(string name, string value) { this.name = name; this.value = value; } public string Value { get { return value; } } public string Name { get { return name; } } } } } } </code></pre> <p>This is the test input I was using:</p> <pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt; &lt;ConfigurationRelease&gt; &lt;Profiles&gt; &lt;Profile Name ="MyProfileName"&gt; &lt;Screens&gt; &lt;Screen Id="MyScreenId"&gt; &lt;Settings&gt; &lt;Setting Name="MySettingName"&gt; &lt;Paydirt&gt;Good stuff&lt;/Paydirt&gt; &lt;/Setting&gt; &lt;/Settings&gt; &lt;/Screen&gt; &lt;/Screens&gt; &lt;/Profile&gt; &lt;Profile Name ="SomeProfile"&gt; &lt;Screens&gt; &lt;Screen Id="MyScreenId"&gt; &lt;Settings&gt; &lt;Setting Name="Boring"&gt; &lt;Paydirt&gt;NOES you should not find this!!!&lt;/Paydirt&gt; &lt;/Setting&gt; &lt;/Settings&gt; &lt;/Screen&gt; &lt;/Screens&gt; &lt;/Profile&gt; &lt;Profile Name ="SomeProfile"&gt; &lt;Screens&gt; &lt;Screen Id="Boring"&gt; &lt;Settings&gt; &lt;Setting Name="MySettingName"&gt; &lt;Paydirt&gt;NOES you should not find this!!!&lt;/Paydirt&gt; &lt;/Setting&gt; &lt;/Settings&gt; &lt;/Screen&gt; &lt;/Screens&gt; &lt;/Profile&gt; &lt;Profile Name ="Boring"&gt; &lt;Screens&gt; &lt;Screen Id="MyScreenId"&gt; &lt;Settings&gt; &lt;Setting Name="MySettingName"&gt; &lt;Paydirt&gt;NOES you should not find this!!!&lt;/Paydirt&gt; &lt;/Setting&gt; &lt;/Settings&gt; &lt;/Screen&gt; &lt;/Screens&gt; &lt;/Profile&gt; &lt;/Profiles&gt; &lt;/ConfigurationRelease&gt; </code></pre> <p>And this is the output I got.</p> <pre><code>C:\Sandbox\XPathInCE\XPathInCE\bin\Debug&gt;XPathInCE MyXmlFile.xml ConfigurationRe lease/Profiles/Profile[Name='MyProfileName']/Screens/Screen[Id='MyScreenId']/Set tings/Setting[Name='MySettingName'] Considering element: ConfigurationRelease Considering element: Profiles Considering element: Profile Considering element: Screens Considering element: Screen Considering element: Settings Considering element: Setting XPath match found! Element Paydirt Attributes Element value: Good stuff Considering element: Profile Skipping Considering element: Profile Skipping Considering element: Profile Skipping Press ENTER to exit </code></pre> <p>I ran it on desktop but it was a CF 2.00 .exe I generated so it should work fine on CE. As you can see it skips when it doesn't match so it wont walk the whole file.</p> <p>Feedback from anyone is appreciated, especially if people have pointers to make the code more concise.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload