当XML父节点和子节点具有相同名称时,如何使用LINQ to XML

时间:2014-11-04 04:23:16

标签: c# .net xml linq-to-xml

我正在尝试从Microsoft Dynamics环境中将一些SQL数据提取到XML,我目前正在使用C#中的LINQ To XML来读取和写入我的XML文件。我需要的一个数据来自一个名为SECURITYSUBROLE的视图。查看此视图​​的结构显示,还有一个名为SECURITYSUBROLE的列。我常用的提取方法给了我这个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>

当我稍后尝试导入此数据时,我收到错误,因为父XML节点与子节点具有相同的名称。以下是导入方法的片段:

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++;
   }
  }
}

它目前在XmlReader.ReadToFollowing上失败了,由于名称混淆,它不知道下一步该去哪里。所以我的问题有两个部分:

1)除了XML之外,还有更好的方法来提取这些数据吗?

2)有没有办法通过LINQ To XML,我能以某种方式区分名称完全相同的父节点和子节点?

2 个答案:

答案 0 :(得分:1)

要获取SECURITYSUBROLE的元素(在您的情况下),您可以检查元素是否有子元素:

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

答案 1 :(得分:0)

我将提出一个不同的方法:

1)VS2013(也可能是早期版本)具有从XML源创建类的功能。因此,获取一个XML文件并将内容复制到剪贴板。然后在新的类文件Edit - &gt; Paste Special - &gt; Paste XML as Classes

2)查看XmlSerialization,它允许您将XML文件转换为具有强类型类的内存对象。

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