XML имеет несколько узлов значений

Обновлено: я могу перейти только к первому узлу значения в моем XML. Приведенный ниже код переходит к первому узлу значения и показывает данные, но как мне выбрать другой узел? На данный момент мне нужно только 3 значения из каждого узла элемента. Налоговый год, номер счета и appl_amt, а также путь к изображению — это единственные значения, над получением которых я работаю. Добавленный Xml — это только часть. Добавляемый раздел повторяется несколько раз, пока теги BatchCompiler/Batch/transactions/transaction не закроют группировки.

   <?xml version="1.0"?>
 <BatchCompiler>
<batch>
   <batchid>95531</batchid>
   <transactions>
        <transaction>
            <items>
              <item>
                <values>
                  <value>
                     <name>doc_type</name>
                     <data>1</data> 
                  </value>
                  <value>
                    <name>doc_id</name>
                    <data>10</data>
                 </value>
                   <value>
                    <name>Bill Base Number</name>
                    <data>0007956700</data>
                 </value>
                 <value>
                    <name>Tax Year</name>
                    <data>2015</data>
                </value>
                 <value>
                    <name>Year For</name>
                    <data>2015</data> 
               </value>
                <value>
                   <name>Listing Type</name>
                   <data>0000</data>
              </value>
               <value>
                  <name>Postmark Date</name>
                   <data>08212015</data>
             </value>
            <value>
                   <name>appl_amt</name>
                   <data>18.12</data>
            </value>
            <value>
                    <name>tran_num</name>
                    <data>1</data>
           </value>
           <value>
                   <name>tran_seq</name>
                   <data>1</data>
           </value>
          </values>
          <image>..\images\95531_1_S_1.tif</image>
     </item>

 namespace GETZIP2
 {
 class Program
 {
    static void Main(string[] args)
    {
        XmlDocument doc = new XmlDocument();
        doc.Load("\\example\\index.xml);  
        MessageBox.Show(doc.SelectSingleNode("BatchCompiler/batch/transactions/transaction/items/item/values/value").InnerText);

    }

    }

 }

person drummerORcoder    schedule 09.09.2015    source источник
comment
SelectSingleNode — это имя метода, говорящее само за себя, не так ли?   -  person Bgl86    schedule 09.09.2015
comment
Взгляните на LINQ to XML.   -  person Sybren    schedule 09.09.2015
comment
Было бы намного лучше, если бы вы использовали атрибуты: <value name="doc_type" data="1" />, которые намного меньше строк.   -  person user9993    schedule 09.09.2015
comment
@ user9993 да, я думал об этом, возможно, придется посмотреть, смогу ли я переформатировать этот файл.   -  person drummerORcoder    schedule 09.09.2015
comment
См. ответ 2 на следующей веб-странице. Часто использовал его: атрибуты в древовидной структуре c Sharp"> stackoverflow.com/questions/28976601/   -  person jdweng    schedule 09.09.2015


Ответы (2)


LINQ to XML — гораздо лучший API, чем старый XmlDocument DOM, а методы запросов LINQ to XML намного приятнее, чем возиться с XPath.

Что-то вроде этого, вероятно, сработает, хотя было бы полезно, если бы вы показали некоторый XML и немного более конкретно указали, какие значения вам действительно нужны.

var doc = XDocument.Load(@"\example\index.xml");

foreach (var value in doc.Descendants("value"))
{
    var name = (string)value.Element("name");
    var data = (string)value.Element("data");

    // do something with these
}

Если вы хотите запросить определенную пару ключ/значение, вы можете сделать что-то вроде:

var taxYear = doc.Descendants("value")
    .Where(e => (string)e.Element("name") == "Tax Year")
    .Select(e => (string)e.Element("data")
    .Single();

Вы даже можете подумать о создании словаря всех пар ключ/значение:

var keyValues = doc.Descendants("value")
    .ToDictionary(e => (string)e.Element("name"), e => (string)e.Element("data"));

var taxYear = keyValues["TaxYear"];
var billNumber = keyValues["Bill Base Number"];
person Charles Mager    schedule 09.09.2015
comment
Спасибо, я добавил XML и информацию о значениях, над которыми я работаю. - person drummerORcoder; 09.09.2015
comment
@drummerORcoder Я обновил, добавив некоторые подробности после добавления вашего XML. - person Charles Mager; 09.09.2015
comment
Когда я пытаюсь использовать метод словаря, я получаю «System.ArgumentException»: элемент с таким же ключом уже добавлен. - person drummerORcoder; 16.09.2015
comment
Кажется, я не могу обойти тот факт, что все значения находятся в элементах с одинаковыми именами (имя/данные) - person drummerORcoder; 16.09.2015
comment
@drummerORcoder это вряд ли будет проблемой, поскольку код будет работать с (частичным) опубликованным вами XML. Я предполагаю, что ваш XML имеет несколько элементов item, и каждый из них содержит элементы value с одним и тем же name. Возможно, вы могли бы повторить каждый item, используя doc.Descendants("item"), а затем создать словарь из каждого из них. - person Charles Mager; 16.09.2015

Помимо Linq to XML, вы также можете использовать класс XmlReader. Он предлагает такие функции, как ReadToNextSibling, которые помогут вам перемещаться между братьями и сестрами.

Другие функции, такие как ReadToDescendant и MoveToNextAttribute, могут пригодиться.

XmlReader reader = XmlReader.Create(@"\example\index.xml");

// Move to the desired element.
reader.MoveToContent();
reader.ReadToDescendant("value");
person Hamed    schedule 09.09.2015
comment
Некоторые элементы XML не являются узлами содержимого. Эта функция продолжает считывать элементы, пока не достигнет узла содержимого, а затем вернет этот узел как объект XmlNodeType. Дополнительная информация - person Hamed; 16.09.2015