none
linq recursion set xml node given path RRS feed

  • Question

  • wish to fill a blank xml document by passing the complete paths to
    leaf nodes (elements or attributes) as parameters to a function that
    implements creating the entire path to the end node element or attribute
    and setting the value. Also if the path contains an index 'n' , the
    function creates the nodes for the all the 1 to n indices if they do not
    exist.

    How do I achieve this using LINQ?

    For example if I pass Path as : "Root.A.B[1].C.D[4].E"
    Value as : "ele"
    document : empty xml document

    It should create the path if it does not exist and set the value of the end node value to ele as follows

    <Root>
     <A>
      <B>
       <C>
        </D>
        </D>
        </D>
        <D>
         <E>ele</E>
        </D>
       </C>
      </B>
     </A>
    </Root>

    Also if the now pass the path : "Root.A.B[1].C.D[4].E@f"
    Value as "attr"

    It should update the document to

    <Root>
     <A>
      <B>
       <C>
        </D>
        </D>
        </D>
        <D>
         <E f="attr">ele</E>
        </D>
       </C>
      </B>
     </A>
    </Root>
    Tuesday, March 8, 2016 3:50 PM

Answers

  • Alright gentlemen, I will answer my own question.

    I ended up writing this function.. (no recurssion) .. splitting the code into multiple posts due to restrictions in size ..

    using System;

    using System.Collections;

    using System.IO;

    using System.Linq;

    using System.Xml.Linq;

    using System.Xml.XPath;

    using Mapper;

    namespace System.Xml.Linq

    {

        [Author("Silas Immanuel Peterson", version = 1.1, created = "03/09/2016", modified = "03/09/2016")]

        public static class  Utilities

        {

            public static System.Xml.Linq.XDocument FillXmlDocument(this System.Xml.Linq.XDocument xdoc, string xPath, object value)

            {

                xPath = xPath.Replace(

                ".", "/");

                string[] pathParts = xPath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);

                bool isrootNode = true;

                XElement rootNode;

                string tempPath = "";

                int count = pathParts.Count();

                int tempCount = 0;

                try

                {

                    foreach (string pathpart in pathParts)

                    {

                        string pathPart = pathpart;

                        tempCount++;

                        if (isrootNode)

                        {

                            if (!pathPart.Contains("@"))

                            {

                                if (pathPart.Contains("["))

                                {

                                    throw new Exception("Root node cannot be an array.");

                                }

                                try

                                {

                                    XElement test = xdoc.Element(pathPart);

                                    if (test == null)

                                    {

                                        TextReader tr = new StringReader("<" + pathPart + "/>");

                                        xdoc =

                                        XDocument.Load(tr);

                                    }

                                    tempPath +=

                                    "//" + pathPart;

                                }

                                catch (Exception ex)

                                {

                                    throw;

                                }

                            }

                            else

                            {

                                throw new Exception("Root node cannot be an attribute");

                            }

                            isrootNode =

                            false;

                        }

    Wednesday, March 9, 2016 9:58 PM
  • else

                        {

                            if (!pathPart.Contains("@"))

                            {

                                string tempprePath = tempPath;

                                if (pathPart.Contains("["))

                                {

                                    string[] forIndex = pathPart.Split(new char[] { '[', ']' }, StringSplitOptions.RemoveEmptyEntries);

                                    if (forIndex.Count() == 2)

                                    {

                                        pathPart = forIndex[0] +

                                        "[" + (int.Parse(string.IsNullOrEmpty(forIndex[1]) ? "0" : string.IsNullOrEmpty(forIndex[1].Trim()) ? "0" : forIndex[1].Trim()) + 1) + "]";

                                    }

                                    else if (forIndex.Count() == 1)

                                    {

                                        pathPart = forIndex[0] +

                                        "[1]";

                                    }

                                }

                                tempPath +=

                                "/" + pathPart;

                                XElement test = xdoc.XPathSelectElement(tempPath);

                                if (test == null)

                                {

                                    if (pathPart.Contains("["))

                                    {

                                        string[] forIndex = pathPart.Split(new char[] { '[', ']' }, StringSplitOptions.RemoveEmptyEntries);

                                        if (forIndex == null)

                                        {

                                            throw new Exception(string.Format("Invalid path or index {0}", tempPath));

                                        }

                                        if (forIndex.Count() == 2)

                                        {

                                            int howmany = 0;

                                            if (int.TryParse(forIndex[1], out howmany))

                                            {

                                                for (int i = 1; i <= howmany; i++)

                                                {

                                                    XElement testtemp = xdoc.XPathSelectElement(tempprePath + "/" + forIndex[0] + "[" + i.ToString(CultureInfo.InvariantCulture) + "]");

                                                    if (testtemp == null)

                                                    {

                                                        xdoc.XPathSelectElement(tempprePath).Add(

                                                        new XElement(forIndex[0]));

                                                    }

                                                }

                                            }

                                            else

                                            {

                                                throw new Exception(string.Format("Invalid path or index {0}", tempPath));

                                            }

                                        }

                                    }

                                    else

                                        xdoc.XPathSelectElement(tempprePath).Add(

                                        new XElement(pathPart));

                                }

                                if (tempCount == count)

                                {

                                    xdoc.XPathSelectElement(tempPath).Value = value.ToString();

                                }

                            }

    Wednesday, March 9, 2016 9:58 PM
  • else if (tempCount == count)

                            {

                               

                              

                               string tempprePath = tempPath;

                                tempPath += "/" + pathPart;

                                XElement test = xdoc.XPathSelectElement(tempprePath);

                                if (test == null)

                                {

                                    string[] tempparts = tempprePath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);

                                    string tempstr = "";

                                    for (int i = 0; i < tempparts.Length -1; i++)

                                    {

                                        tempstr += "/" + tempparts[i];

                                    }

                                    xdoc.XPathSelectElement(tempstr).Add(new XElement(tempparts[tempparts.Count() - 1]));

                                    pathPart = pathPart.Replace("@", "");

                                    xdoc.XPathSelectElement(tempprePath).SetAttributeValue(pathPart, value);

                                }

                                else

                                {

                                    bool attribSet = false;

                                    foreach (XAttribute attr in ((IEnumerable)

                                        xdoc.XPathEvaluate(tempPath)).OfType<XAttribute>())

                                    {

                                        attribSet = true;

                                        attr.Value = value.ToString();

                                    }

                                    if (!attribSet)

                                    {

                                        try

                                        {

                                            pathPart = pathPart.Replace("@", "");

                                          

                                            xdoc.XPathSelectElement(tempprePath).SetAttributeValue(pathPart, value);

                                          

                                          

                                        }

                                        catch (Exception ddd)

                                        {

                                           

                                            throw;

                                        }

                                    }

                                }

                            }

                            else

                            {

                                string tempprePath = tempPath;

                                tempPath +=

                                "/" + pathPart;

                                XElement test = xdoc.XPathSelectElement(tempPath);

                                if (test == null)

                                {

                                    throw new Exception("Root node cannot be an attribute");

                                }

                            }

                        }

                    }

                }

                catch (Exception outerEx)

                {

                    throw;

                }

                return xdoc;

            }

        }

    [System.AttributeUsage(System.AttributeTargets.Class |

                            System.AttributeTargets.Struct) ]

        public class Author : System.Attribute

        {

            private string name;

            public double version;

            public string created;

            public string modified;

           

           

            public Author(string name)

            {

                this.name = name;

                version = 1.0;

            }

        }

    }



    Wednesday, March 9, 2016 9:59 PM

All replies

  • Hello,

    you can't achieve it directly using LINQ, you need split your path with comma, then loop the array and handle the array to achieve it.

    Wednesday, March 9, 2016 7:21 AM
  • Alright gentlemen, I will answer my own question.

    I ended up writing this function.. (no recurssion) .. splitting the code into multiple posts due to restrictions in size ..

    using System;

    using System.Collections;

    using System.IO;

    using System.Linq;

    using System.Xml.Linq;

    using System.Xml.XPath;

    using Mapper;

    namespace System.Xml.Linq

    {

        [Author("Silas Immanuel Peterson", version = 1.1, created = "03/09/2016", modified = "03/09/2016")]

        public static class  Utilities

        {

            public static System.Xml.Linq.XDocument FillXmlDocument(this System.Xml.Linq.XDocument xdoc, string xPath, object value)

            {

                xPath = xPath.Replace(

                ".", "/");

                string[] pathParts = xPath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);

                bool isrootNode = true;

                XElement rootNode;

                string tempPath = "";

                int count = pathParts.Count();

                int tempCount = 0;

                try

                {

                    foreach (string pathpart in pathParts)

                    {

                        string pathPart = pathpart;

                        tempCount++;

                        if (isrootNode)

                        {

                            if (!pathPart.Contains("@"))

                            {

                                if (pathPart.Contains("["))

                                {

                                    throw new Exception("Root node cannot be an array.");

                                }

                                try

                                {

                                    XElement test = xdoc.Element(pathPart);

                                    if (test == null)

                                    {

                                        TextReader tr = new StringReader("<" + pathPart + "/>");

                                        xdoc =

                                        XDocument.Load(tr);

                                    }

                                    tempPath +=

                                    "//" + pathPart;

                                }

                                catch (Exception ex)

                                {

                                    throw;

                                }

                            }

                            else

                            {

                                throw new Exception("Root node cannot be an attribute");

                            }

                            isrootNode =

                            false;

                        }

    Wednesday, March 9, 2016 9:58 PM
  • else

                        {

                            if (!pathPart.Contains("@"))

                            {

                                string tempprePath = tempPath;

                                if (pathPart.Contains("["))

                                {

                                    string[] forIndex = pathPart.Split(new char[] { '[', ']' }, StringSplitOptions.RemoveEmptyEntries);

                                    if (forIndex.Count() == 2)

                                    {

                                        pathPart = forIndex[0] +

                                        "[" + (int.Parse(string.IsNullOrEmpty(forIndex[1]) ? "0" : string.IsNullOrEmpty(forIndex[1].Trim()) ? "0" : forIndex[1].Trim()) + 1) + "]";

                                    }

                                    else if (forIndex.Count() == 1)

                                    {

                                        pathPart = forIndex[0] +

                                        "[1]";

                                    }

                                }

                                tempPath +=

                                "/" + pathPart;

                                XElement test = xdoc.XPathSelectElement(tempPath);

                                if (test == null)

                                {

                                    if (pathPart.Contains("["))

                                    {

                                        string[] forIndex = pathPart.Split(new char[] { '[', ']' }, StringSplitOptions.RemoveEmptyEntries);

                                        if (forIndex == null)

                                        {

                                            throw new Exception(string.Format("Invalid path or index {0}", tempPath));

                                        }

                                        if (forIndex.Count() == 2)

                                        {

                                            int howmany = 0;

                                            if (int.TryParse(forIndex[1], out howmany))

                                            {

                                                for (int i = 1; i <= howmany; i++)

                                                {

                                                    XElement testtemp = xdoc.XPathSelectElement(tempprePath + "/" + forIndex[0] + "[" + i.ToString(CultureInfo.InvariantCulture) + "]");

                                                    if (testtemp == null)

                                                    {

                                                        xdoc.XPathSelectElement(tempprePath).Add(

                                                        new XElement(forIndex[0]));

                                                    }

                                                }

                                            }

                                            else

                                            {

                                                throw new Exception(string.Format("Invalid path or index {0}", tempPath));

                                            }

                                        }

                                    }

                                    else

                                        xdoc.XPathSelectElement(tempprePath).Add(

                                        new XElement(pathPart));

                                }

                                if (tempCount == count)

                                {

                                    xdoc.XPathSelectElement(tempPath).Value = value.ToString();

                                }

                            }

    Wednesday, March 9, 2016 9:58 PM
  • else if (tempCount == count)

                            {

                               

                              

                               string tempprePath = tempPath;

                                tempPath += "/" + pathPart;

                                XElement test = xdoc.XPathSelectElement(tempprePath);

                                if (test == null)

                                {

                                    string[] tempparts = tempprePath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);

                                    string tempstr = "";

                                    for (int i = 0; i < tempparts.Length -1; i++)

                                    {

                                        tempstr += "/" + tempparts[i];

                                    }

                                    xdoc.XPathSelectElement(tempstr).Add(new XElement(tempparts[tempparts.Count() - 1]));

                                    pathPart = pathPart.Replace("@", "");

                                    xdoc.XPathSelectElement(tempprePath).SetAttributeValue(pathPart, value);

                                }

                                else

                                {

                                    bool attribSet = false;

                                    foreach (XAttribute attr in ((IEnumerable)

                                        xdoc.XPathEvaluate(tempPath)).OfType<XAttribute>())

                                    {

                                        attribSet = true;

                                        attr.Value = value.ToString();

                                    }

                                    if (!attribSet)

                                    {

                                        try

                                        {

                                            pathPart = pathPart.Replace("@", "");

                                          

                                            xdoc.XPathSelectElement(tempprePath).SetAttributeValue(pathPart, value);

                                          

                                          

                                        }

                                        catch (Exception ddd)

                                        {

                                           

                                            throw;

                                        }

                                    }

                                }

                            }

                            else

                            {

                                string tempprePath = tempPath;

                                tempPath +=

                                "/" + pathPart;

                                XElement test = xdoc.XPathSelectElement(tempPath);

                                if (test == null)

                                {

                                    throw new Exception("Root node cannot be an attribute");

                                }

                            }

                        }

                    }

                }

                catch (Exception outerEx)

                {

                    throw;

                }

                return xdoc;

            }

        }

    [System.AttributeUsage(System.AttributeTargets.Class |

                            System.AttributeTargets.Struct) ]

        public class Author : System.Attribute

        {

            private string name;

            public double version;

            public string created;

            public string modified;

           

           

            public Author(string name)

            {

                this.name = name;

                version = 1.0;

            }

        }

    }



    Wednesday, March 9, 2016 9:59 PM