Does anyone know of an existing means of creating an XML hierarchy programatically from an XPath expression?
For example if I have an XML fragment such as:
<feed> <entry> <data></data> <content></content> </entry> </feed>
Given the XPath expression /feed/entry/content/@source I would have:
<feed> <entry> <data></data> <content @source=""></content> </entry> </feed>
I realize this is possible using XSLT but due to the dynamic nature of what I'm trying to accomplish a fixed transformation won't work.
I am working in C# but if someone has a solution using some other language please chime in.
Thanks for the help!
Steps to Using XPathCreate a DocumentBuilder. Create a Document from a file or stream. Create an Xpath object and an XPath path expression. Compile the XPath expression using XPath.
XPath uses path expressions to select nodes or node-sets in an XML document. These path expressions look very much like the expressions you see when you work with a traditional computer file system. XPath expressions can be used in JavaScript, Java, XML Schema, PHP, Python, C and C++, and lots of other languages.
In the example you present the only thing being created is the attribute ...
XmlElement element = (XmlElement)doc.SelectSingleNode("/feed/entry/content"); if (element != null) element.SetAttribute("source", "");
If what you really want is to be able to create the hierarchy where it doesn't exist then you could your own simple xpath parser. I don't know about keeping the attribute in the xpath though. I'd rather cast the node as an element and tack on a .SetAttribute as I've done here:
static private XmlNode makeXPath(XmlDocument doc, string xpath) { return makeXPath(doc, doc as XmlNode, xpath); } static private XmlNode makeXPath(XmlDocument doc, XmlNode parent, string xpath) { // grab the next node name in the xpath; or return parent if empty string[] partsOfXPath = xpath.Trim('/').Split('/'); string nextNodeInXPath = partsOfXPath.First(); if (string.IsNullOrEmpty(nextNodeInXPath)) return parent; // get or create the node from the name XmlNode node = parent.SelectSingleNode(nextNodeInXPath); if (node == null) node = parent.AppendChild(doc.CreateElement(nextNodeInXPath)); // rejoin the remainder of the array as an xpath expression and recurse string rest = String.Join("/", partsOfXPath.Skip(1).ToArray()); return makeXPath(doc, node, rest); } static void Main(string[] args) { XmlDocument doc = new XmlDocument(); doc.LoadXml("<feed />"); makeXPath(doc, "/feed/entry/data"); XmlElement contentElement = (XmlElement)makeXPath(doc, "/feed/entry/content"); contentElement.SetAttribute("source", ""); Console.WriteLine(doc.OuterXml); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With