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

本文关键字:提取 数据 xmlReader 读取 | 更新日期: 2023-09-27 17:57:33

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)一样,即使我尝试了两个不同的读取器指针,但现在出现了异常。

不需要什么帮助,感谢

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

您可以读取每个<InformationTuple>中的第一个<Name>元素,如下所示。介绍以下扩展方法:

public static partial class XmlReaderExtensions
{
    public static IEnumerable<string> ReadAllElementContentsAsString(this XmlReader reader, string localName, string namespaceURI)
    {
        while (reader.ReadToFollowing(localName, namespaceURI))
            yield return reader.ReadElementContentAsString();
    }
    public static IEnumerable<XmlReader> ReadAllSubtrees(this XmlReader reader, string localName, string namespaceURI)
    {
        while (reader.ReadToFollowing(localName, namespaceURI))
            using (var subReader = reader.ReadSubtree())
                yield return subReader;
    }
}

然后做:

foreach (var name in reader.ReadAllSubtrees("InformationTuple", "")
    .Select(r => r.ReadAllElementContentsAsString("Name", "").First()))
{
    // Process the name somehow
    Debug.WriteLine(name);
}

如果只想读取每个<InformationTuples>容器内每个<InformationTuple>元素的第一个<Name>元素,可以通过使用SelectMany():对ReadAllSubtrees()进行调用来限制搜索范围

foreach (var name in reader.ReadAllSubtrees("InformationTuples", "")
    .SelectMany(r => r.ReadAllSubtrees("InformationTuple", ""))
    .Select(r => r.ReadAllElementContentsAsString("Name", "").First()))
{
    // Process the name somehow
    Debug.WriteLine(name);
}

一些注意事项:

  • 当你用完ReadSubtree()子树阅读器时,你不会关闭(或处理)它

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

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

  • 一开始您对reader.ReadToFollowing("InformationTuple");的调用过多。也许你打算做reader.ReadToFollowing("InformationTuples");

  • 为确保每个<InformationTuple>有一个且只有一个<Name>元素,用.Single()替换First()

  • 如果每个<InformationTuple>可能有多个<Name>节点,并且您想读取所有节点,请执行以下操作:

    foreach (var name in reader.ReadAllSubtrees("InformationTuple", "")
        .SelectMany(r => r.ReadAllElementContentsAsString("Name", "")))
    {
        // Process the name somehow
    

在这里演示小提琴。

下面的代码我用了很多,不会产生任何错误。

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; }
    }
}