Я пытаюсь извлечь некоторые данные 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, чтобы я мог каким-то образом различать родительский и дочерний узлы, названные точно так же?
Чтобы получить элементы (в вашем случае) для SECURITYSUBROLE
вы можете проверить, есть ли у элемента дочерние элементы:
XElement root = XElement.Load(path);
var subroles = root.Descendants("SECURITYSUBROLE") // all subroles
.Where(x => !x.HasElements); // only subroles without children
Я собираюсь предложить другой подход:
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();
Descendants
? ИспользуйтеElements
вместо этого, и вы должны быть в порядке.