Member 13050667 Ответов: 2

C#: как читать подобные узлы из XML с помощью LINQ


У меня есть большой XML-файл, который я хочу прочитать в своем приложении и сохранить некоторые значения в пользовательском классе. В файле есть несколько узлов <tu>. (новый класс TUs / раздел tu). Проблемная часть связана с узлом <seg>. (каждый <tu> имеет два <seg> узла с одним и тем же родительским узлом, но с разным атрибутом (языком)).
Как вы можете видеть, мой базовый скрипт поймает один и тот же (первый) узел <seg> дважды.

<tu creationdate="20130619T135814Z" creationid="ANA" changedate="20130619T135814Z" changeid="ANA" lastusagedate="20130619T135814Z">
      <prop type="x-LastUsedBy">ANA</prop>
      <prop type="x-Origin">TM</prop>
      <prop type="x-OriginalFormat">TradosTranslatorsWorkbench</prop>
      <tuv xml:lang="de-DE">
        <seg>Die Teile werden im Querdurchlauf transportiert.<ph x="1" type="1" /></seg>
      </tuv>
      <tuv xml:lang="en-GB">
        <seg>The parts are transported in a cross conveyance.<ph x="1" type="1" /></seg>
      </tuv>
    </tu>


Что я уже пробовал:

XDocument xDoc;
           xDoc = XDocument.Load(path);

           var result = from q in xDoc.Descendants("tu")
                        select new TUs
                        {
                            SOURCE = q.Element("tuv").Element("seg").Value,
                            TARGET = q.Element("tuv").Element("seg").Value,
                        };

           foreach (TUs TU in result)
           {
               Console.WriteLine(TU.SOURCE);
               Console.WriteLine(TU.TARGET);
           }

2 Ответов

Рейтинг:
12

RickZeeland

Вот решение, которое лучше работает с несколькими узлами tu:

XDocument xDoc = XDocument.Load(path);

foreach (XElement tu in xDoc.Root.Descendants("tu"))
{
    Console.WriteLine("tu = " + tu.Attribute("creationid").Value);

    foreach (XElement tuv in tu.Descendants("tuv"))
    {
        if (tuv.ToString().Contains("\"en-GB\""))
        {
            Console.WriteLine("seg = " + tuv.Descendants("seg").First().Value);
        }
    }

    Console.WriteLine();
}

XML-данные должны иметь корневой элемент:
<Root>
<tu creationdate="20130619T135814Z" creationid="John" changedate="20130619T135814Z" changeid="John" lastusagedate="20130619T135814Z">
  <prop type="x-LastUsedBy">John</prop>
  <prop type="x-Origin">TM</prop>
  <prop type="x-OriginalFormat">TestTool</prop>
  <tuv xml:lang="de-DE">
    <seg>This is the German text</seg>
  </tuv>
  <tuv xml:lang="en-GB">
    <seg>This is the English text</seg>
  </tuv>
</tu>
<tu creationdate="20130619T135814Z" creationid="Rick" changedate="20130619T135814Z" changeid="Rick" lastusagedate="20130619T135814Z">
  <prop type="x-LastUsedBy">Rick</prop>
  <prop type="x-Origin">TM</prop>
  <prop type="x-OriginalFormat">TestTool</prop>
  <tuv xml:lang="de-DE">
    <seg>This is Ricks German text</seg>
  </tuv>
  <tuv xml:lang="en-GB">
    <seg>This is Ricks English text</seg>
  </tuv>
</tu>
</Root>


Рейтинг:
1

RickZeeland

Это может работать только в том случае, если ваш XML - файл правильно отформатирован:

XDocument xDoc;
xDoc = XDocument.Load(path);

foreach (var node in xDoc.Root.Descendants().Where(n => n.Name == "seg"))
{
    Console.WriteLine(node.Name + " = " + node.Value);
}

данные XML:
<tu creationdate="20130619T135814Z" creationid="John" changedate="20130619T135814Z" changeid="John" lastusagedate="20130619T135814Z">
  <prop type="x-LastUsedBy">
    John
    <prop type="x-Origin">
      TM
      <prop type="x-OriginalFormat">
        TestTool
        <tuv xml:lang="de-DE">
          <seg>This is the German text</seg>
        </tuv>
        <tuv xml:lang="en-GB">
          <seg>This is the English text</seg>
        </tuv>
      </prop>
    </prop>
  </prop>
</tu>


Member 13050667

Спасибо, что нашли время помочь мне!
К сожалению, Ваш метод возвращает эти узлы в отдельном цикле. Однако я должен сохранить содержимое 4 узлов из A <tu>. (то, что я спросил, было просто проблемной частью 2 узлов из 4) есть ли лучший способ? Я имею в виду другие методы рядом с LINQ... которые могут работать?!