读取多个子节点并在c#中提取数据xmlReader

时间:2016-07-17 19:29:51

标签: c# xml

XML:

<InformationTuples>
      <InformationTuple>
       <Name>documentClass</Name>
        <value format="" valueset="{rechnung}" originalValue="Rechnung" start="0" end="0" LD="0" doc="C:\b4enviam-service-test\inputDir\031a0933-2616-4d8e-8a79-56746ae0e160/Invoice_51029062.pdf">Rechnung</value>
        <EntityType>Class</EntityType>
        <state>New       </state>
        <need>Mandatory </need>
        <extractionmethod>
        </extractionmethod>
        <weight>1</weight>
        <precondition type="optional">All</precondition>
      </InformationTuple>
      <InformationTuple>
        <Name>SAPNr.</Name>
        <value format="" valueset="" originalValue="4352020616" start="0" end="0" LD="0" doc="C:\b4enviam-service-test\inputDir\031a0933-2616-4d8e-8a79-56746ae0e160/Invoice_51029062.pdf">4352020616</value>
        <EntityType>KB.GTInovice</EntityType>
        <state>New       </state>
        <need>Mandatory </need>
        <extractionmethod>
        </extractionmethod>
        <weight>1</weight>
        <precondition type="optional">all</precondition>
      </InformationTuple>
      <InformationTuple>
        <Name>GT-Invoice</Name>
        <value format="" valueset="" originalValue="" start="0" end="0" LD="0" doc="">
        </value>
        <EntityType>KB.GTInovice</EntityType>
        <state>New       </state>
        <need>Mandatory </need>
        <extractionmethod>
        </extractionmethod>
        <weight>1</weight>
        <precondition type="optional">all</precondition>
      </InformationTuple>
    </InformationTuples>

C#

reader.ReadToFollowing("InformationTuple");
                   reader2.ReadToFollowing("InformationTuple");



                   do
                   {
                       subtree = reader2.ReadSubtree();
                       subtree.ReadToFollowing("Name");
                       Debug.WriteLine(subtree.ReadElementContentAsString());
                       reader2.ReadToNextSibling("InfromationTuple");



                   } while (reader.ReadToNextSibling("InformationTuple"))

我现在尝试使用c#从XML中提取多个子节点的数据但是没有成功。我尝试了多个代码片段但无法提取数据。

就像我必须提取三个信息元组中给出的数据一样,但XMLreader中给出的函数无法正常工作,读取器指针在单循环迭代后无法移动(无法移动到第二个InformationTuple),即使我尝试了两个不同的读取器指针但是它现在给予例外。

需要一些帮助, 谢谢

2 个答案:

答案 0 :(得分:1)

您可以使用以下方法阅读每个<Name>元素中的<InformationTuple>元素:

    static IEnumerable<string> ReadNames(XmlReader reader)
    {
        while (reader.ReadToFollowing("InformationTuple"))
        {
            using (var subReader = reader.ReadSubtree())
            {
                subReader.ReadToFollowing("Name");
                var name = subReader.ReadElementContentAsString();
                yield return name;
            }
        }
    }

一些注意事项:

  • 完成后,您不会关闭(或处置)ReadSubtree()子树阅读器。来自docs

      

    在新阅读器关闭之前,您不应对原始阅读器执行任何操作。此操作不受支持,可能导致不可预测的行为。

    因此,在推进外部阅读器之前,必须关闭或处置此嵌套阅读器。

  • 您在开始时拨打过多reader.ReadToFollowing("InformationTuple");。也许你打算做reader.ReadToFollowing("InformationTuples");

如果您只想阅读每个<Name>容器中每个<InformationTuple>元素的<InformationTuples>元素,您可以执行以下操作:

    static IEnumerable<string> ReadNestedNames(XmlReader reader)
    {
        foreach (var subReader in reader.ReadSubtrees("InformationTuples").SelectMany(r => r.ReadSubtrees("InformationTuple")))
        {
            subReader.ReadToFollowing("Name");
            var name = subReader.ReadElementContentAsString();
            yield return name;
        }
    }

使用扩展方法:

public static class XmlReaderExtensions
{
    public static IEnumerable<XmlReader> ReadSubtrees(this XmlReader reader, string name)
    {
        while (reader.ReadToFollowing(name))
        {
            using (var subReader = reader.ReadSubtree())
                yield return subReader;
        }
    }
}

答案 1 :(得分:0)

下面的代码我经常使用,不会产生任何错误。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XmlReader reader = XmlReader.Create(FILENAME);
            while (!reader.EOF)
            {
                if (reader.Name != "InformationTuple")
                {
                    reader.ReadToFollowing("InformationTuple");
                }
                if (!reader.EOF)
                {
                    XElement subtree = (XElement)XElement.ReadFrom(reader);
                    Info.info.Add(new Info() { state = (string)subtree.Element("state"), weight = (int)subtree.Element("weight") });
                }
            }
        }
    }
    public class Info
    {
        public static List<Info> info = new List<Info>();
        public string state { get; set; }
        public int weight { get; set; }

    }
}