如何将平面重复 xml 属性读取到单独的对象中
How can I read flat repeating xml attributes into separate objects
我有一个 XML 文件,其中包含一些我需要读入单独对象的结果。我的问题是数据包含在单个节点中。
我需要读取的属性也会根据不同的结果而变化,所以它不像使用TAKE之类的东西那么简单。
这是一个结果:
<AnalyteCode>HEM</AnalyteCode>
<AnalyteName>HEM</AnalyteName>
<Result>18.0</Result>
<ResultText>0</ResultText>
但是,这也是:
<AnalyteCode>ALP</AnalyteCode>
<AnalyteName>ALP SerPl-cCnc</AnalyteName>
<Result>52.0</Result>
<Units>U/L</Units>
<LowRange>20.0</LowRange>
<HighRange>150.0</HighRange>
为简洁起见,我省略了一些 XML
<LabResults>
<LabResult>
<LabResultHeader>
<TestCode>CDP</TestCode>
<TestName>Comprehensive Diagnostic</TestName>
<TestType>R</TestType>
<ResultDate>2019-06-14T12:08:41-07:00</ResultDate>
<ResultStatus>Done</ResultStatus>
<DeviceID>XXXXXXYYYYYZZZZZ</DeviceID>
</LabResultHeader>
<LabResultItems>
<LabResultItem>
<AnalyteCode>HEM</AnalyteCode>
<AnalyteName>HEM</AnalyteName>
<Result>18.0</Result>
<ResultText>0</ResultText>
<AnalyteCode>LIP</AnalyteCode>
<AnalyteName>LIP</AnalyteName>
<Result>107.0</Result>
<ResultText>0</ResultText>
<AnalyteCode>ICT</AnalyteCode>
<AnalyteName>ICT</AnalyteName>
<Result>0.0</Result>
<ResultText>0</ResultText>
<AnalyteCode>ALB</AnalyteCode>
<AnalyteName>Alb SerPl-mCnc</AnalyteName>
<Result>37.0</Result>
<Units>g/L</Units>
<LowRange>25.0</LowRange>
<HighRange>44.0</HighRange>
<AnalyteCode>ALP</AnalyteCode>
<AnalyteName>ALP SerPl-cCnc</AnalyteName>
<Result>52.0</Result>
<Units>U/L</Units>
<LowRange>20.0</LowRange>
<HighRange>150.0</HighRange>
<AnalyteCode>ALT</AnalyteCode>
<AnalyteName>ALT SerPl-cCnc</AnalyteName>
<Result>54.0</Result>
<Units>U/L</Units>
<LowRange>10.0</LowRange>
<HighRange>118.0</HighRange>
<AnalyteCode>AMY</AnalyteCode>
<AnalyteName>Amylase SerPl-cCnc</AnalyteName>
<Result>320.0</Result>
<Units>U/L</Units>
<LowRange>200.0</LowRange>
<HighRange>1200.0</HighRange>
<AnalyteCode>TBIL</AnalyteCode>
<AnalyteName>Bilirub SerPl-sCnc</AnalyteName>
<Result>4.0</Result>
<Units>umol/L</Units>
<LowRange>2.0</LowRange>
<HighRange>10.0</HighRange>
<AnalyteCode>BUN</AnalyteCode>
<AnalyteName>BUN SerPl-sCnc</AnalyteName>
<Result>4.8</Result>
<Units>mmol/L</Units>
<LowRange>2.5</LowRange>
<HighRange>8.9</HighRange>
<AnalyteCode>CA</AnalyteCode>
<AnalyteName>Calcium SerPl-sCnc</AnalyteName>
<Result>2.87</Result>
<Units>mmol/L</Units>
<LowRange>2.15</LowRange>
<HighRange>2.95</HighRange>
<AnalyteCode>PHOS</AnalyteCode>
<AnalyteName>Phosphate SerPl-sCnc</AnalyteName>
<ResultText>2.38 *</ResultText>
<Units>mmol/L</Units>
<LowRange>0.94</LowRange>
<HighRange>2.13</HighRange>
<Notes>H</Notes>
<AnalyteCode>CRE</AnalyteCode>
<AnalyteName>Creat SerPl-sCnc</AnalyteName>
<Result>57.0</Result>
<Units>umol/L</Units>
<LowRange>27.0</LowRange>
<HighRange>124.0</HighRange>
<AnalyteCode>GLU</AnalyteCode>
<AnalyteName>Glucose SerPl-sCnc</AnalyteName>
<ResultText>6.2 *</ResultText>
<Units>mmol/L</Units>
<LowRange>3.3</LowRange>
<HighRange>6.1</HighRange>
<Notes>H</Notes>
<AnalyteCode>NA+</AnalyteCode>
<AnalyteName>Sodium SerPl-sCnc</AnalyteName>
<Result>149.0</Result>
<Units>mmol/L</Units>
<LowRange>138.0</LowRange>
<HighRange>160.0</HighRange>
<AnalyteCode>K+</AnalyteCode>
<AnalyteName>Potassium SerPl-sCnc</AnalyteName>
<Result>4.7</Result>
<Units>mmol/L</Units>
<LowRange>3.7</LowRange>
<HighRange>5.8</HighRange>
<AnalyteCode>TP</AnalyteCode>
<AnalyteName>Prot SerPl-mCnc</AnalyteName>
<Result>58.0</Result>
<Units>g/L</Units>
<LowRange>54.0</LowRange>
<HighRange>82.0</HighRange>
<AnalyteCode>GLOB</AnalyteCode>
<AnalyteName>Globulin SerPl Calc-mCnc</AnalyteName>
<ResultText>21 *</ResultText>
<Units>g/L</Units>
<LowRange>23.0</LowRange>
<HighRange>52.0</HighRange>
<Notes>L</Notes>
</LabResultItem>
</LabResultItems>
</LabResult>
</LabResults>
如果每个结果总是以一个属性开头(例如;"AnalyteCode"),那么您可以使用它作为 "starting" 分隔符来解析每个组。
我创建了一些示例代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
namespace Test_20191203
{
public class LabResultItem
{
public string AnalyteCode { get; set; }
public string AnalyteName { get; set; }
public string Result { get; set; }
public string ResultText { get; set; }
public string Units { get; set; }
public string LowRange { get; set; }
public string HighRange { get; set; }
public string Notes { get; set; }
}
public class Program
{
static void Main(string[] args)
{
string startProperty = nameof(LabResultItem.AnalyteCode);
XmlDocument doc = new XmlDocument();
doc.LoadXml(input);
List<LabResultItem> results = new List<LabResultItem>();
LabResultItem currentItem = new LabResultItem();
foreach (XmlNode node in doc.SelectSingleNode("/LabResults/LabResult/LabResultItems/LabResultItem").ChildNodes)
{
if (node.Name == startProperty)
{
results.Add(currentItem);
currentItem = new LabResultItem();
}
var prop = typeof(LabResultItem).GetProperty(node.Name);
if(prop == null)
{
throw new Exception($"Invalid node found in xml: '{node.Name}', property must be a part of {nameof(LabResultItem)}");
}
prop.SetValue(currentItem, node.InnerText, null);
}
foreach(var result in results)
{
// iterate through results
}
}
const string input = @"<LabResults>
<LabResult>
<LabResultHeader>
<TestCode>CDP</TestCode>
<TestName>Comprehensive Diagnostic</TestName>
<TestType>R</TestType>
<ResultDate>2019-06-14T12:08:41-07:00</ResultDate>
<ResultStatus>Done</ResultStatus>
<DeviceID>XXXXXXYYYYYZZZZZ</DeviceID>
</LabResultHeader>
<LabResultItems>
<LabResultItem>
<AnalyteCode>HEM</AnalyteCode>
<AnalyteName>HEM</AnalyteName>
<Result>18.0</Result>
<ResultText>0</ResultText>
<AnalyteCode>LIP</AnalyteCode>
<AnalyteName>LIP</AnalyteName>
<Result>107.0</Result>
<ResultText>0</ResultText>
<AnalyteCode>ICT</AnalyteCode>
<AnalyteName>ICT</AnalyteName>
<Result>0.0</Result>
<ResultText>0</ResultText>
<AnalyteCode>ALB</AnalyteCode>
<AnalyteName>Alb SerPl-mCnc</AnalyteName>
<Result>37.0</Result>
<Units>g/L</Units>
<LowRange>25.0</LowRange>
<HighRange>44.0</HighRange>
<AnalyteCode>ALP</AnalyteCode>
<AnalyteName>ALP SerPl-cCnc</AnalyteName>
<Result>52.0</Result>
<Units>U/L</Units>
<LowRange>20.0</LowRange>
<HighRange>150.0</HighRange>
<AnalyteCode>ALT</AnalyteCode>
<AnalyteName>ALT SerPl-cCnc</AnalyteName>
<Result>54.0</Result>
<Units>U/L</Units>
<LowRange>10.0</LowRange>
<HighRange>118.0</HighRange>
<AnalyteCode>AMY</AnalyteCode>
<AnalyteName>Amylase SerPl-cCnc</AnalyteName>
<Result>320.0</Result>
<Units>U/L</Units>
<LowRange>200.0</LowRange>
<HighRange>1200.0</HighRange>
<AnalyteCode>TBIL</AnalyteCode>
<AnalyteName>Bilirub SerPl-sCnc</AnalyteName>
<Result>4.0</Result>
<Units>umol/L</Units>
<LowRange>2.0</LowRange>
<HighRange>10.0</HighRange>
<AnalyteCode>BUN</AnalyteCode>
<AnalyteName>BUN SerPl-sCnc</AnalyteName>
<Result>4.8</Result>
<Units>mmol/L</Units>
<LowRange>2.5</LowRange>
<HighRange>8.9</HighRange>
<AnalyteCode>CA</AnalyteCode>
<AnalyteName>Calcium SerPl-sCnc</AnalyteName>
<Result>2.87</Result>
<Units>mmol/L</Units>
<LowRange>2.15</LowRange>
<HighRange>2.95</HighRange>
<AnalyteCode>PHOS</AnalyteCode>
<AnalyteName>Phosphate SerPl-sCnc</AnalyteName>
<ResultText>2.38 *</ResultText>
<Units>mmol/L</Units>
<LowRange>0.94</LowRange>
<HighRange>2.13</HighRange>
<Notes>H</Notes>
<AnalyteCode>CRE</AnalyteCode>
<AnalyteName>Creat SerPl-sCnc</AnalyteName>
<Result>57.0</Result>
<Units>umol/L</Units>
<LowRange>27.0</LowRange>
<HighRange>124.0</HighRange>
<AnalyteCode>GLU</AnalyteCode>
<AnalyteName>Glucose SerPl-sCnc</AnalyteName>
<ResultText>6.2 *</ResultText>
<Units>mmol/L</Units>
<LowRange>3.3</LowRange>
<HighRange>6.1</HighRange>
<Notes>H</Notes>
<AnalyteCode>NA+</AnalyteCode>
<AnalyteName>Sodium SerPl-sCnc</AnalyteName>
<Result>149.0</Result>
<Units>mmol/L</Units>
<LowRange>138.0</LowRange>
<HighRange>160.0</HighRange>
<AnalyteCode>K+</AnalyteCode>
<AnalyteName>Potassium SerPl-sCnc</AnalyteName>
<Result>4.7</Result>
<Units>mmol/L</Units>
<LowRange>3.7</LowRange>
<HighRange>5.8</HighRange>
<AnalyteCode>TP</AnalyteCode>
<AnalyteName>Prot SerPl-mCnc</AnalyteName>
<Result>58.0</Result>
<Units>g/L</Units>
<LowRange>54.0</LowRange>
<HighRange>82.0</HighRange>
<AnalyteCode>GLOB</AnalyteCode>
<AnalyteName>Globulin SerPl Calc-mCnc</AnalyteName>
<ResultText>21 *</ResultText>
<Units>g/L</Units>
<LowRange>23.0</LowRange>
<HighRange>52.0</HighRange>
<Notes>L</Notes>
</LabResultItem>
</LabResultItems>
</LabResult>
</LabResults>";
}
}
我有一个 XML 文件,其中包含一些我需要读入单独对象的结果。我的问题是数据包含在单个节点中。
我需要读取的属性也会根据不同的结果而变化,所以它不像使用TAKE之类的东西那么简单。
这是一个结果:
<AnalyteCode>HEM</AnalyteCode>
<AnalyteName>HEM</AnalyteName>
<Result>18.0</Result>
<ResultText>0</ResultText>
但是,这也是:
<AnalyteCode>ALP</AnalyteCode>
<AnalyteName>ALP SerPl-cCnc</AnalyteName>
<Result>52.0</Result>
<Units>U/L</Units>
<LowRange>20.0</LowRange>
<HighRange>150.0</HighRange>
为简洁起见,我省略了一些 XML
<LabResults>
<LabResult>
<LabResultHeader>
<TestCode>CDP</TestCode>
<TestName>Comprehensive Diagnostic</TestName>
<TestType>R</TestType>
<ResultDate>2019-06-14T12:08:41-07:00</ResultDate>
<ResultStatus>Done</ResultStatus>
<DeviceID>XXXXXXYYYYYZZZZZ</DeviceID>
</LabResultHeader>
<LabResultItems>
<LabResultItem>
<AnalyteCode>HEM</AnalyteCode>
<AnalyteName>HEM</AnalyteName>
<Result>18.0</Result>
<ResultText>0</ResultText>
<AnalyteCode>LIP</AnalyteCode>
<AnalyteName>LIP</AnalyteName>
<Result>107.0</Result>
<ResultText>0</ResultText>
<AnalyteCode>ICT</AnalyteCode>
<AnalyteName>ICT</AnalyteName>
<Result>0.0</Result>
<ResultText>0</ResultText>
<AnalyteCode>ALB</AnalyteCode>
<AnalyteName>Alb SerPl-mCnc</AnalyteName>
<Result>37.0</Result>
<Units>g/L</Units>
<LowRange>25.0</LowRange>
<HighRange>44.0</HighRange>
<AnalyteCode>ALP</AnalyteCode>
<AnalyteName>ALP SerPl-cCnc</AnalyteName>
<Result>52.0</Result>
<Units>U/L</Units>
<LowRange>20.0</LowRange>
<HighRange>150.0</HighRange>
<AnalyteCode>ALT</AnalyteCode>
<AnalyteName>ALT SerPl-cCnc</AnalyteName>
<Result>54.0</Result>
<Units>U/L</Units>
<LowRange>10.0</LowRange>
<HighRange>118.0</HighRange>
<AnalyteCode>AMY</AnalyteCode>
<AnalyteName>Amylase SerPl-cCnc</AnalyteName>
<Result>320.0</Result>
<Units>U/L</Units>
<LowRange>200.0</LowRange>
<HighRange>1200.0</HighRange>
<AnalyteCode>TBIL</AnalyteCode>
<AnalyteName>Bilirub SerPl-sCnc</AnalyteName>
<Result>4.0</Result>
<Units>umol/L</Units>
<LowRange>2.0</LowRange>
<HighRange>10.0</HighRange>
<AnalyteCode>BUN</AnalyteCode>
<AnalyteName>BUN SerPl-sCnc</AnalyteName>
<Result>4.8</Result>
<Units>mmol/L</Units>
<LowRange>2.5</LowRange>
<HighRange>8.9</HighRange>
<AnalyteCode>CA</AnalyteCode>
<AnalyteName>Calcium SerPl-sCnc</AnalyteName>
<Result>2.87</Result>
<Units>mmol/L</Units>
<LowRange>2.15</LowRange>
<HighRange>2.95</HighRange>
<AnalyteCode>PHOS</AnalyteCode>
<AnalyteName>Phosphate SerPl-sCnc</AnalyteName>
<ResultText>2.38 *</ResultText>
<Units>mmol/L</Units>
<LowRange>0.94</LowRange>
<HighRange>2.13</HighRange>
<Notes>H</Notes>
<AnalyteCode>CRE</AnalyteCode>
<AnalyteName>Creat SerPl-sCnc</AnalyteName>
<Result>57.0</Result>
<Units>umol/L</Units>
<LowRange>27.0</LowRange>
<HighRange>124.0</HighRange>
<AnalyteCode>GLU</AnalyteCode>
<AnalyteName>Glucose SerPl-sCnc</AnalyteName>
<ResultText>6.2 *</ResultText>
<Units>mmol/L</Units>
<LowRange>3.3</LowRange>
<HighRange>6.1</HighRange>
<Notes>H</Notes>
<AnalyteCode>NA+</AnalyteCode>
<AnalyteName>Sodium SerPl-sCnc</AnalyteName>
<Result>149.0</Result>
<Units>mmol/L</Units>
<LowRange>138.0</LowRange>
<HighRange>160.0</HighRange>
<AnalyteCode>K+</AnalyteCode>
<AnalyteName>Potassium SerPl-sCnc</AnalyteName>
<Result>4.7</Result>
<Units>mmol/L</Units>
<LowRange>3.7</LowRange>
<HighRange>5.8</HighRange>
<AnalyteCode>TP</AnalyteCode>
<AnalyteName>Prot SerPl-mCnc</AnalyteName>
<Result>58.0</Result>
<Units>g/L</Units>
<LowRange>54.0</LowRange>
<HighRange>82.0</HighRange>
<AnalyteCode>GLOB</AnalyteCode>
<AnalyteName>Globulin SerPl Calc-mCnc</AnalyteName>
<ResultText>21 *</ResultText>
<Units>g/L</Units>
<LowRange>23.0</LowRange>
<HighRange>52.0</HighRange>
<Notes>L</Notes>
</LabResultItem>
</LabResultItems>
</LabResult>
</LabResults>
如果每个结果总是以一个属性开头(例如;"AnalyteCode"),那么您可以使用它作为 "starting" 分隔符来解析每个组。
我创建了一些示例代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
namespace Test_20191203
{
public class LabResultItem
{
public string AnalyteCode { get; set; }
public string AnalyteName { get; set; }
public string Result { get; set; }
public string ResultText { get; set; }
public string Units { get; set; }
public string LowRange { get; set; }
public string HighRange { get; set; }
public string Notes { get; set; }
}
public class Program
{
static void Main(string[] args)
{
string startProperty = nameof(LabResultItem.AnalyteCode);
XmlDocument doc = new XmlDocument();
doc.LoadXml(input);
List<LabResultItem> results = new List<LabResultItem>();
LabResultItem currentItem = new LabResultItem();
foreach (XmlNode node in doc.SelectSingleNode("/LabResults/LabResult/LabResultItems/LabResultItem").ChildNodes)
{
if (node.Name == startProperty)
{
results.Add(currentItem);
currentItem = new LabResultItem();
}
var prop = typeof(LabResultItem).GetProperty(node.Name);
if(prop == null)
{
throw new Exception($"Invalid node found in xml: '{node.Name}', property must be a part of {nameof(LabResultItem)}");
}
prop.SetValue(currentItem, node.InnerText, null);
}
foreach(var result in results)
{
// iterate through results
}
}
const string input = @"<LabResults>
<LabResult>
<LabResultHeader>
<TestCode>CDP</TestCode>
<TestName>Comprehensive Diagnostic</TestName>
<TestType>R</TestType>
<ResultDate>2019-06-14T12:08:41-07:00</ResultDate>
<ResultStatus>Done</ResultStatus>
<DeviceID>XXXXXXYYYYYZZZZZ</DeviceID>
</LabResultHeader>
<LabResultItems>
<LabResultItem>
<AnalyteCode>HEM</AnalyteCode>
<AnalyteName>HEM</AnalyteName>
<Result>18.0</Result>
<ResultText>0</ResultText>
<AnalyteCode>LIP</AnalyteCode>
<AnalyteName>LIP</AnalyteName>
<Result>107.0</Result>
<ResultText>0</ResultText>
<AnalyteCode>ICT</AnalyteCode>
<AnalyteName>ICT</AnalyteName>
<Result>0.0</Result>
<ResultText>0</ResultText>
<AnalyteCode>ALB</AnalyteCode>
<AnalyteName>Alb SerPl-mCnc</AnalyteName>
<Result>37.0</Result>
<Units>g/L</Units>
<LowRange>25.0</LowRange>
<HighRange>44.0</HighRange>
<AnalyteCode>ALP</AnalyteCode>
<AnalyteName>ALP SerPl-cCnc</AnalyteName>
<Result>52.0</Result>
<Units>U/L</Units>
<LowRange>20.0</LowRange>
<HighRange>150.0</HighRange>
<AnalyteCode>ALT</AnalyteCode>
<AnalyteName>ALT SerPl-cCnc</AnalyteName>
<Result>54.0</Result>
<Units>U/L</Units>
<LowRange>10.0</LowRange>
<HighRange>118.0</HighRange>
<AnalyteCode>AMY</AnalyteCode>
<AnalyteName>Amylase SerPl-cCnc</AnalyteName>
<Result>320.0</Result>
<Units>U/L</Units>
<LowRange>200.0</LowRange>
<HighRange>1200.0</HighRange>
<AnalyteCode>TBIL</AnalyteCode>
<AnalyteName>Bilirub SerPl-sCnc</AnalyteName>
<Result>4.0</Result>
<Units>umol/L</Units>
<LowRange>2.0</LowRange>
<HighRange>10.0</HighRange>
<AnalyteCode>BUN</AnalyteCode>
<AnalyteName>BUN SerPl-sCnc</AnalyteName>
<Result>4.8</Result>
<Units>mmol/L</Units>
<LowRange>2.5</LowRange>
<HighRange>8.9</HighRange>
<AnalyteCode>CA</AnalyteCode>
<AnalyteName>Calcium SerPl-sCnc</AnalyteName>
<Result>2.87</Result>
<Units>mmol/L</Units>
<LowRange>2.15</LowRange>
<HighRange>2.95</HighRange>
<AnalyteCode>PHOS</AnalyteCode>
<AnalyteName>Phosphate SerPl-sCnc</AnalyteName>
<ResultText>2.38 *</ResultText>
<Units>mmol/L</Units>
<LowRange>0.94</LowRange>
<HighRange>2.13</HighRange>
<Notes>H</Notes>
<AnalyteCode>CRE</AnalyteCode>
<AnalyteName>Creat SerPl-sCnc</AnalyteName>
<Result>57.0</Result>
<Units>umol/L</Units>
<LowRange>27.0</LowRange>
<HighRange>124.0</HighRange>
<AnalyteCode>GLU</AnalyteCode>
<AnalyteName>Glucose SerPl-sCnc</AnalyteName>
<ResultText>6.2 *</ResultText>
<Units>mmol/L</Units>
<LowRange>3.3</LowRange>
<HighRange>6.1</HighRange>
<Notes>H</Notes>
<AnalyteCode>NA+</AnalyteCode>
<AnalyteName>Sodium SerPl-sCnc</AnalyteName>
<Result>149.0</Result>
<Units>mmol/L</Units>
<LowRange>138.0</LowRange>
<HighRange>160.0</HighRange>
<AnalyteCode>K+</AnalyteCode>
<AnalyteName>Potassium SerPl-sCnc</AnalyteName>
<Result>4.7</Result>
<Units>mmol/L</Units>
<LowRange>3.7</LowRange>
<HighRange>5.8</HighRange>
<AnalyteCode>TP</AnalyteCode>
<AnalyteName>Prot SerPl-mCnc</AnalyteName>
<Result>58.0</Result>
<Units>g/L</Units>
<LowRange>54.0</LowRange>
<HighRange>82.0</HighRange>
<AnalyteCode>GLOB</AnalyteCode>
<AnalyteName>Globulin SerPl Calc-mCnc</AnalyteName>
<ResultText>21 *</ResultText>
<Units>g/L</Units>
<LowRange>23.0</LowRange>
<HighRange>52.0</HighRange>
<Notes>L</Notes>
</LabResultItem>
</LabResultItems>
</LabResult>
</LabResults>";
}
}