从 C# 中的大 xml 读取子节点值
Posted
技术标签:
【中文标题】从 C# 中的大 xml 读取子节点值【英文标题】:Reading a child node value from a big xml in C# 【发布时间】:2020-09-12 06:03:37 【问题描述】:我有来自服务的 4000 行 xmlresponse。我使用所需的标签名称从那个大 xml 中提取了特定部分
XmlNodeList xmlForms = xmlDoc.GetElementsByTagName("Form");
从此节点示例部分 xml 如下所示
<Form>
<FormID>3434294</FormID>
<StatusDate>0001-01-01T00:00:00</StatusDate>
<InternalFormNo>CADFADSFSAGDSADG01</InternalFormNo>
<ExternalFormNo>CADFASDFASFSC1001</ExternalFormNo>
<ProposalDescription>Treatment</ProposalDescription>
<ProposalForm>false</ProposalForm>
<StateApprovals>
<StateApproval>
<StateApprovalID>2245363363636</StateApprovalID>
<IssueLimitSet>
<IssueLimitSetID>88</IssueLimitSetID>
<Name>AccAdv</Name>
<Note />
<ModifyDate>0001-01-01T00:00:00</ModifyDate>
<IssueLimits>
<IssueLimit>
<IssueLimtID>80</IssueLimtID>
<GIAmount>62</GIAmount>
<SIAmount>0.00</SIAmount>
<ChangeProcessingCGIAmount>0</ChangeProcessingCGIAmount>
<MaximumMultiSelect>0</MaximumMultiSelect>
<CreateDate>0001-01-01T00:00:00</CreateDate>
<ModifyDate>0001-01-01T00:00:00</ModifyDate>
</IssueLimit>
</IssueLimits>
</IssueLimitSet>
<SpecialProcessing>false</SpecialProcessing>
<ModifyUser>TESTUSER</ModifyUser>
<ModifyDate>2016-02-17T17:52:59.163</ModifyDate>
</StateApproval>
</StateApprovals>
</Form>
我需要读取节点 GIAmount 并提取它的值 (62)。但是 xpath 表示法总是给我空值。如何从此子 xml 中读取此子节点。简单的 xpath 也总是给出 null 。
foreach (XmlNode form in xmlForms)
var statusDate= form.SelectSingleNode("/Form/StatusDate"); //This always null i am getting
----------------原始xml------------在Variations->Forms->Form下 --在某些情况下,出现多个表单标签,我需要读取每个表单中的特定节点-------
<?xml version="1.0" encoding="utf-8"?>
<Product xmlns="http://testtest.com/twmku">
<ProductID>72</ProductID>
<InternalDescription>AccidentAdvance</InternalDescription>
<ExternalDescription>AccidentAdvance</ExternalDescription>
<Variations>
<Variation>
<VariationID>231</VariationID>
<InternalDescription>AccidentAdvance123</InternalDescription>
<ExternalDescription>AccidentAdvance</ExternalDescription>
<ProposalDescription />
<IsProposalReady>false</IsProposalReady>
<StatusDate>2009-03-26T00:00:00</StatusDate>
<EffectiveDate>2009-04-01T00:00:00</EffectiveDate>
<WithdrawnDate>0001-01-01T00:00:00</WithdrawnDate>
<ModifyUser>Utesruser</ModifyUser>
<ModifyDate>2011-11-30T10:35:26.313</ModifyDate>
<Employers />
<Forms>
<Form>
<FormID>3493</FormID>
<IsGeneric>true</IsGeneric>
<HasLimitsInUnits>true</HasLimitsInUnits>
<Description>AccAdv Master Policy</Description>
<CreateUser>US\testMW</CreateUser>
<CreateDate>0001-01-01T00:00:00</CreateDate>
<ModifyUser>US\testMW</ModifyUser>
<ModifyDate>2011-12-12T11:42:40.06</ModifyDate>
<DataElements />
<StateApprovals>
<StateApproval>
<StateApprovalID>2256556</StateApprovalID>
<IssueLimitSet>
<IssueLimitSetID>88</IssueLimitSetID>
<Name>AccAdv Modtest</Name>
<Note />
<ModifyDate>0001-01-01T00:00:00</ModifyDate>
<IssueLimits>
<IssueLimit>
<IssueLimtID>80</IssueLimtID>
<Keyword>AccAdv Mod 1</Keyword>
<MinMarketingLimit>0.50</MinMarketingLimit>
<MaxMarketingLimit>12.00</MaxMarketingLimit>
<CGIAmount>0.00</CGIAmount>
<GIAmount>6</GIAmount>
<SIAmount>0.00</SIAmount>
<ChangeProcessingCGIAmount>0</ChangeProcessingCGIAmount>
<CreateDate>0001-01-01T00:00:00</CreateDate>
<ModifyDate>0001-01-01T00:00:00</ModifyDate>
</IssueLimit>
</IssueLimits>
</IssueLimitSet>
<StateRequirementSet />
<QuestionSet />
<SICSet />
<DateFiled>0001-01-01T00:00:00</DateFiled>
<SpecialProcessing>false</SpecialProcessing>
<ModifyUser>JBtestD</ModifyUser>
<ModifyDate>2016-02-18T14:39:50.927</ModifyDate>
</StateApproval>
</StateApprovals>
<Parameters />
<IsSelected>true</IsSelected>
</Form>
<Form>
<FormID>3495</FormID>
<IsGeneric>true</IsGeneric>
<HasLimitsInUnits>true</HasLimitsInUnits>
<Description>AccAdv Master main</Description>
<CreateUser>US\testMqW</CreateUser>
<CreateDate>0001-01-01T00:00:00</CreateDate>
<ModifyUser>US\testMW</ModifyUser>
<ModifyDate>2011-12-12T11:42:40.06</ModifyDate>
<DataElements />
<StateApprovals>
<StateApproval>
<StateApprovalID>26556</StateApprovalID>
<IssueLimitSet>
<IssueLimitSetID>88</IssueLimitSetID>
<Name>AccAdv Moretest</Name>
<Note />
<ModifyDate>0001-01-01T00:00:00</ModifyDate>
<IssueLimits>
<IssueLimit>
<IssueLimtID>84</IssueLimtID>
<Keyword>AccAdv Mod 1</Keyword>
<MinMarketingLimit>0.50</MinMarketingLimit>
<MaxMarketingLimit>12.00</MaxMarketingLimit>
<CGIAmount>0.00</CGIAmount>
<GIAmount>34</GIAmount>
<SIAmount>0.00</SIAmount>
<ChangeProcessingCGIAmount>0</ChangeProcessingCGIAmount>
<CreateDate>0001-01-01T00:00:00</CreateDate>
<ModifyDate>0001-01-01T00:00:00</ModifyDate>
</IssueLimit>
</IssueLimits>
</IssueLimitSet>
<StateRequirementSet />
<QuestionSet />
<SICSet />
<DateFiled>0001-01-01T00:00:00</DateFiled>
<SpecialProcessing>false</SpecialProcessing>
<ModifyUser>JBtestD</ModifyUser>
<ModifyDate>2016-02-18T14:39:50.927</ModifyDate>
</StateApproval>
</StateApprovals>
<Parameters />
<IsSelected>true</IsSelected>
</Form>
</Forms>
<ParameterValueSets />
<AllowCustomRates>false</AllowCustomRates>
</Variation>
</Variations>
</Product>
【问题讨论】:
【参考方案1】:您已经以Form
元素为目标,因此没有理由将它包含在XPath 中。只需跳过该标记,并使用其后代组成路径。
在你的情况下:"StateApprovals/StateApproval/IssueLimitSet/IssueLimits/GIAmount"
或者,更简洁:"//GIAmount"
请注意,我的回答是基于您帖子的片段,路径可能会根据实际内容发生变化。
【讨论】:
我尝试了所有选项仍然为空。当我观察到我的 xml 不必要的 xmlns 命名空间被随机添加时。我不确定为什么 xpath 表达式对我不起作用,在我读的一篇文章中,因为 xmlns xpath 不起作用,我们需要删除。但如果它在一个地方我们可以删除,甚至尝试使用正则表达式删除仍然总是给出 null。【参考方案2】:最好使用LINQ to XML。使用它的方法,很容易获得任何 XML 元素。
(1) 您的 XML 具有默认命名空间。需要考虑到这一点。 (2) 多个<Form>...</Form>
元素需要一个循环。
c#
void Main()
XElement xelem = XElement.Parse(@"<Product xmlns='http://testtest.com/twmku'>
<ProductID>72</ProductID>
<InternalDescription>AccidentAdvance</InternalDescription>
<ExternalDescription>AccidentAdvance</ExternalDescription>
<Variations>
<Variation>
<VariationID>231</VariationID>
<InternalDescription>AccidentAdvance123</InternalDescription>
<ExternalDescription>AccidentAdvance</ExternalDescription>
<ProposalDescription />
<IsProposalReady>false</IsProposalReady>
<StatusDate>2009-03-26T00:00:00</StatusDate>
<EffectiveDate>2009-04-01T00:00:00</EffectiveDate>
<WithdrawnDate>0001-01-01T00:00:00</WithdrawnDate>
<ModifyUser>Utesruser</ModifyUser>
<ModifyDate>2011-11-30T10:35:26.313</ModifyDate>
<Employers />
<Forms>
<Form>
<FormID>3493</FormID>
<IsGeneric>true</IsGeneric>
<HasLimitsInUnits>true</HasLimitsInUnits>
<Description>AccAdv Master Policy</Description>
<CreateUser>US\testMW</CreateUser>
<CreateDate>0001-01-01T00:00:00</CreateDate>
<ModifyUser>US\testMW</ModifyUser>
<ModifyDate>2011-12-12T11:42:40.06</ModifyDate>
<DataElements />
<StateApprovals>
<StateApproval>
<StateApprovalID>2256556</StateApprovalID>
<IssueLimitSet>
<IssueLimitSetID>88</IssueLimitSetID>
<Name>AccAdv Modtest</Name>
<Note />
<ModifyDate>0001-01-01T00:00:00</ModifyDate>
<IssueLimits>
<IssueLimit>
<IssueLimtID>80</IssueLimtID>
<Keyword>AccAdv Mod 1</Keyword>
<MinMarketingLimit>0.50</MinMarketingLimit>
<MaxMarketingLimit>12.00</MaxMarketingLimit>
<CGIAmount>0.00</CGIAmount>
<GIAmount>6</GIAmount>
<SIAmount>0.00</SIAmount>
<ChangeProcessingCGIAmount>0</ChangeProcessingCGIAmount>
<CreateDate>0001-01-01T00:00:00</CreateDate>
<ModifyDate>0001-01-01T00:00:00</ModifyDate>
</IssueLimit>
</IssueLimits>
</IssueLimitSet>
<StateRequirementSet />
<QuestionSet />
<SICSet />
<DateFiled>0001-01-01T00:00:00</DateFiled>
<SpecialProcessing>false</SpecialProcessing>
<ModifyUser>JBtestD</ModifyUser>
<ModifyDate>2016-02-18T14:39:50.927</ModifyDate>
</StateApproval>
</StateApprovals>
<Parameters />
<IsSelected>true</IsSelected>
</Form>
<Form>
<FormID>3495</FormID>
<IsGeneric>true</IsGeneric>
<HasLimitsInUnits>true</HasLimitsInUnits>
<Description>AccAdv Master main</Description>
<CreateUser>US\testMqW</CreateUser>
<CreateDate>0001-01-01T00:00:00</CreateDate>
<ModifyUser>US\testMW</ModifyUser>
<ModifyDate>2011-12-12T11:42:40.06</ModifyDate>
<DataElements />
<StateApprovals>
<StateApproval>
<StateApprovalID>26556</StateApprovalID>
<IssueLimitSet>
<IssueLimitSetID>88</IssueLimitSetID>
<Name>AccAdv Moretest</Name>
<Note />
<ModifyDate>0001-01-01T00:00:00</ModifyDate>
<IssueLimits>
<IssueLimit>
<IssueLimtID>84</IssueLimtID>
<Keyword>AccAdv Mod 1</Keyword>
<MinMarketingLimit>0.50</MinMarketingLimit>
<MaxMarketingLimit>12.00</MaxMarketingLimit>
<CGIAmount>0.00</CGIAmount>
<GIAmount>34</GIAmount>
<SIAmount>0.00</SIAmount>
<ChangeProcessingCGIAmount>0</ChangeProcessingCGIAmount>
<CreateDate>0001-01-01T00:00:00</CreateDate>
<ModifyDate>0001-01-01T00:00:00</ModifyDate>
</IssueLimit>
</IssueLimits>
</IssueLimitSet>
<StateRequirementSet />
<QuestionSet />
<SICSet />
<DateFiled>0001-01-01T00:00:00</DateFiled>
<SpecialProcessing>false</SpecialProcessing>
<ModifyUser>JBtestD</ModifyUser>
<ModifyDate>2016-02-18T14:39:50.927</ModifyDate>
</StateApproval>
</StateApprovals>
<Parameters />
<IsSelected>true</IsSelected>
</Form>
</Forms>
<ParameterValueSets />
<AllowCustomRates>false</AllowCustomRates>
</Variation>
</Variations>
</Product>");
//string GIAmount = GIAmount.Descendants(ns + "GIAmount").FirstOrDefault().Value;
XNamespace ns = xelem.GetDefaultNamespace();
foreach (var el in xelem.Descendants(ns + "GIAmount"))
Console.WriteLine("GIAmount=0", el.Value);
输出
GIAmount=6
GIAmount=34
【讨论】:
感谢您的回复。您在独立应用程序中工作的示例。当我尝试合并到实际应用程序中时,我得到了 System.Xml.XmlException 异常:'根级别的数据无效。第 1 行,位置 1。当我检查我的表单变量时,添加了不必要的命名空间,但原来它不存在。比如一个值通常是不够的信息。试试下面的 xml linq:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
class Program
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
string xml = File.ReadAllText(FILENAME);
XDocument doc = XDocument.Parse(xml);
XNamespace ns = doc.Root.GetDefaultNamespace();
List<StateApproval> approvals = doc.Descendants(ns + "StateApproval").Select(x => new StateApproval()
id = (string)x.Element(ns + "StateApprovalID"),
limitSetId = (string)x.Descendants(ns + "IssueLimitSetID").FirstOrDefault(),
name = (string)x.Descendants(ns + "Name").FirstOrDefault(),
modifyDate = (DateTime)x.Descendants(ns + "ModifyDate").FirstOrDefault(),
issueLimitId = (string)x.Descendants(ns + "IssueLimtID").FirstOrDefault(),
giAmount = (decimal)x.Descendants(ns + "GIAmount").FirstOrDefault(),
siAmount = (decimal)x.Descendants(ns + "SIAmount").FirstOrDefault(),
changeAmount = (decimal)x.Descendants(ns + "ChangeProcessingCGIAmount").FirstOrDefault(),
min = (decimal)x.Descendants(ns + "MinMarketingLimit").FirstOrDefault(),
max = (decimal)x.Descendants(ns + "MaxMarketingLimit").FirstOrDefault(),
createDate = (DateTime)x.Descendants(ns + "CreateDate").FirstOrDefault(),
).ToList();
public class StateApproval
public string id get; set;
public string limitSetId get; set;
public string name get; set;
public DateTime modifyDate get; set;
public string issueLimitId get; set;
public decimal giAmount get; set;
public decimal siAmount get; set;
public decimal changeAmount get; set;
public decimal min get; set;
public decimal max get; set;
public DateTime createDate get; set;
【讨论】:
我没有提供加载功能的 uri 路径。我的 xml 的运行时子集存在。它也没有转换为字符串。无法尝试您的选项。 用于字符串:XDocument doc = XDocument.Parse(string); 是的,我试过了。这。但对我来说,在解析 xmlexception 根级别的数据时异常给出 line1 位置 1 无效。当我观察到我的 xml 获得不必要的命名空间时。为此,我无法继续进行。 :(以上是关于从 C# 中的大 xml 读取子节点值的主要内容,如果未能解决你的问题,请参考以下文章