Как использовать LINQ to XML, когда родительский и дочерний узлы XML имеют одинаковые имена

1

Я пытаюсь извлечь некоторые данные SQL в XML из среды Microsoft Dynamics, в настоящее время я использую 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, чтобы я мог каким-то образом различать родительский и дочерний узлы, названные точно так же?

  • 0
    Дай угадаю, ты использовал метод Descendants ? Используйте Elements вместо этого, и вы должны быть в порядке.
Теги:
linq-to-xml

2 ответа

1
Лучший ответ

Чтобы получить элементы (в вашем случае) для SECURITYSUBROLE вы можете проверить, есть ли у элемента дочерние элементы:

XElement root = XElement.Load(path);
var subroles = root.Descendants("SECURITYSUBROLE") // all subroles
                   .Where(x => !x.HasElements); // only subroles without children
  • 0
    Это было бы идеальным решением, если бы я имел дело с XML-файлами нормального размера, потому что я использовал XmlReader, потому что генерируемые XML-файлы иногда имеют размер до 2 ГБ или более и приводят к исключению нехватки памяти, если я пытаюсь загрузить все это в объект XElement. Есть ли способ по-прежнему использовать ваше решение при использовании XmlReader?
  • 0
    @crypticApps В заголовке вашего вопроса написано Linq-to-xml, это не XmlReader. Почему бы вам не сделать свой проект 64-битным и не установить различные флаги компиляции, которые позволят вам использовать много памяти. Если вы хотите знать, как это сделать, задайте это как отдельный вопрос.
Показать ещё 1 комментарий
0

Я собираюсь предложить другой подход:

1) VS2013 (возможно, более ранние версии) имеет функцию для создания класса из источника XML. Получите один из ваших XML файлов и скопируйте содержимое в буфер обмена. Затем в новом файле класса EditPaste SpecialPaste XML as Classes

2) Посмотрите на XmlSerialization которая позволит вам преобразовать XML файл в объект памяти с строго типизированным классом.

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню