在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)一样,即使我尝试了两个不同的读取器指针,但现在出现了异常。
不需要什么帮助,感谢
您可以读取每个<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; }
}
}