How to use LINQ to XML when XML parent and child nodes have the same name

て烟熏妆下的殇ゞ 提交于 2020-01-05 07:23:07

问题


I am trying to extract some SQL data to XML from a Microsoft Dynamics environment, I am currently using LINQ To XML in C# to read and write to my XML files. One piece of data I need is from a view called SECURITYSUBROLE. Looking at the structure of this view shows that there is a column also named SECURITYSUBROLE. My normal method of extraction has given me this XML.

<SECURITYSUBROLE>
  <SECURITYROLE>886301</SECURITYROLE>
  <SECURITYSUBROLE>886317</SECURITYSUBROLE>
  <VALIDFROM>1900-01-01T00:00:00-06:00</VALIDFROM>
  <VALIDFROMTZID>0</VALIDFROMTZID>
  <VALIDTO>1900-01-01T00:00:00-06:00</VALIDTO>
  <VALIDTOTZID>0</VALIDTOTZID>
  <RECVERSION>1</RECVERSION>
  <RECID>886317</RECID>
</SECURITYSUBROLE>

When I try to import this data later on, I am getting errors because the parent XML node has the same name as a child node. Here is a snippet of the import method:

XmlReaderSettings settings = new XmlReaderSettings();
settings.CheckCharacters = false;

XmlReader reader = XmlReader.Create(path, settings);

reader.MoveToContent();
int count = 1;
List<XElement> xmlSubset = new List<XElement>();
while (reader.ReadToFollowing(xmlTag))
 {
   if (count % 1000 == 0)
   {
    xmlSubset.Add(XElement.Load(reader.ReadSubtree()));
    XDocument xmlTemp = new XDocument(new XElement(xmlTag));
    foreach (XElement elem in xmlSubset)
    {
     xmlTemp.Root.Add(elem);
     }
     xmlSubset = new List<XElement>();
     ImportTableByName(connectionString, tableName, xmlTemp);
     count = 1;
     }
   else
   {
     xmlSubset.Add(XElement.Load(reader.ReadSubtree()));
     count++;
   }
  }
}

It's currently failing on the XmlReader.ReadToFollowing, where it doesn't know where to go next because of the name confusion. So my question has two parts:

1) Is there some better way to be extracting this data other than to XML?

2) Is there a way through LINQ To XML that I can somehow differentiate between the parent and child nodes named exactly the same?


回答1:


To get the elements (in your case) for SECURITYSUBROLE you can check to see if the element's have children:

XElement root = XElement.Load(path);
var subroles = root.Descendants("SECURITYSUBROLE") // all subroles
                   .Where(x => !x.HasElements); // only subroles without children



回答2:


I'm going to suggest a different approach:

1) VS2013 (possibly earlier versions too) has a function to create a class from an XML source. So get one of your XML files and copy the content to your clipboard. Then in a new class file Edit --> Paste Special --> Paste XML as Classes

2) Look into XmlSerialization which will allow you to convert an XML file into an in memory object with a strongly typed class.

      XmlSerializer s = new XmlSerializer(yourNewClassTYPE);
      TextReader r = new StreamReader(XmlFileLocation);
      var dataFromYourXmlAsAStronglyTypedClass = (yourNewlyClassTYPE) s.Deserialize(r);
      r.Close();


来源:https://stackoverflow.com/questions/26727732/how-to-use-linq-to-xml-when-xml-parent-and-child-nodes-have-the-same-name

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!