【问题标题】:How to use LINQ to XML when XML parent and child nodes have the same name当 XML 父节点和子节点具有相同名称时如何使用 LINQ to XML
【发布时间】:2014-11-04 04:23:15
【问题描述】:

我正在尝试从 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 节点与子节点具有相同的名称。这是导入方法的sn-p:

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 以某种方式区分名称完全相同的父节点和子节点?

【问题讨论】:

  • 让我猜猜,你用的是Descendants方法?改用Elements 应该没问题。

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


【解决方案1】:

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

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

【讨论】:

  • 如果我正在处理正常大小的 XML 文件,这将是一个完美的解决方案,我使用 XmlReader 的原因是因为生成的 XML 文件有时会达到 2GB 或更大的大小并且会出局如果我尝试将整个内容加载到 XElement 对象中,则会出现内存异常。有没有办法在使用 XmlReader 时仍然利用您的解决方案?
  • @crypticApps 你的问题标题说 Linq-to-xml,那不是 XmlReader。你为什么不让你的项目 64 位,并放入各种编译标志,让你使用大量内存。如果您想知道如何做到这一点,请将其作为一个单独的问题提出。
  • 我接受这个答案,因为它符合我的要求,谢谢 Chuck!
【解决方案2】:

我将建议一种不同的方法:

1) VS2013(也可能是更早的版本)具有从 XML 源创建类的功能。因此,获取您的 XML 文件之一并将内容复制到剪贴板。然后在一个新的类文件中Edit --> Paste Special --> 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();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-11
    相关资源
    最近更新 更多