通用XML阅读器代码
本文关键字:代码 XML 通用 | 更新日期: 2023-09-27 18:08:32
我有一个程序,它解析三个不同的CrystalReport XML文件(结构相似,但后代级别不同),然后将值填充到一个类中。
下面是第一个例子:
public static List<VyplatnePasky> DeserialzieRozuctovanieMzdy(ref List<VyplatnePasky> _pasky, string sPath)
{
XDocument document = XDocument.Load(sPath);
var formattedAreaPairReport = from d in document.Descendants("FormattedReport".AddNamespace())
.Descendants("FormattedAreaPair".AddNamespace())
.Descendants("FormattedAreaPair".AddNamespace())
select d.Element("FormattedAreaPair".AddNamespace());
if (formattedAreaPairReport.Count() == 0)
{
//empty;
InsertErrorMessage("<formattedAreaPairReport> contains no data! No Data to parse from.", "DeserialzieRozuctovanieMzdy");
return _pasky;
}
//check if any sequence contains any matching elements
var GotElements = formattedAreaPairReport.Elements("FormattedAreaPair".AddNamespace()).Where(n=>n.Attribute("Level").Value == "3" && n.Attribute("Type").Value == "Group");
if (GotElements == null)
{
InsertErrorMessage("There are no matching elements under <formattedAreaPairReport>.", "DeserialzieRozuctovanieMzdy");
return _pasky;
}
foreach (XElement xElement in GotElements)
{
RozuctovanieMzda_Values(xElement, ref _pasky);
}
return _pasky;
}
下面是第二个(第二个XML文档解析器):
public static List<VyplatnePasky> DeserializeVyplatnePasky(string sPath)
{
List<VyplatnePasky> _pasky = new List<VyplatnePasky>();
XDocument document = XDocument.Load(sPath);
var formattedAreaPairReport = from d in document.Descendants("FormattedReport".AddNamespace())
select d.Element("FormattedAreaPair".AddNamespace());
if (formattedAreaPairReport.Count() == 0)
{
//empty;
InsertErrorMessage("<formattedAreaPairReport> contains no data! No Data to parse from.", "DeserializeVyplatnePasky");
}
else
{
//sequence contains data
foreach (XElement xElement in formattedAreaPairReport.Elements("FormattedAreaPair".AddNamespace()))
{
VyplatnePasky _paska = new VyplatnePasky();
VyplatnePasky_Items(xElement, ref _paska);
_pasky.Add(_paska);
}
}
return _pasky;
}
从上面的代码中可以看到,所有三种XML解析方法看起来几乎相同;主要的区别是我在后代中有多深,例如formattedAreaPairReport
我想做的是,通过创建可以被所有三个方法使用的泛型void,使这段代码更专业和可重用。
我正在考虑创建多个委托,在那里我将传递我的lambda命令,如:
var formattedAreaPairReport = ProcessFirstLevel(from d in document.Descendants("FormattedReport".AddNamespace())
select d.Element("FormattedAreaPair".AddNamespace()));
然而,它会变成一个大而混乱的空白。
问题是——这真的是可行的/值得做吗?你能帮帮我吗?
您可以使用一些干净的编码技术来DRY代码。试着这样做:
public static List<VyplatnePasky> DeserialzieRozuctovanieMzdy(ref List<VyplatnePasky> _pasky, string sPath)
{
var formattedAreaPairReport =
tryToGetItemsFromDocument
(
sPath,
document=>from d in document.Descendants("FormattedReport".AddNamespace())
.Descendants("FormattedAreaPair".AddNamespace())
.Descendants("FormattedAreaPair".AddNamespace())
select d.Element("FormattedAreaPair".AddNamespace()),
"DeserialzieRozuctovanieMzdy"
);
addItemsToVyplatnePasky(formattedAreaPairReport, ref _pasky);
return _pasky;
}
public static List<VyplatnePasky> DeserializeVyplatnePasky(string sPath)
{
List<VyplatnePasky> _pasky = new List<VyplatnePasky>();
var formattedAreaPairReport =
tryToGetItemsFromDocument
(
sPath,
document=>from d in document.Descendants("FormattedReport".AddNamespace())
select d.Element("FormattedAreaPair".AddNamespace()),
"DeserializeVyplatnePasky"
);
addItemsToVyplatnePasky2(formattedAreaPairReport, _pasky);
return _pasky;
}
private static void addItemsToVyplatnePasky(IEnumerable<XElement> formattedAreaPairReport, ref List<VyplatnePasky> _pasky)
{
if (formattedAreaPairReport.Count() > 0)
{
//check if any sequence contains any matching elements
var GotElements = formattedAreaPairReport.Elements("FormattedAreaPair".AddNamespace()).Where(n=>n.Attribute("Level").Value == "3" && n.Attribute("Type").Value == "Group");
if (GotElements == null)
{
InsertErrorMessage("There are no matching elements under <formattedAreaPairReport>.", "DeserialzieRozuctovanieMzdy");
return;
}
foreach (XElement xElement in GotElements)
{
RozuctovanieMzda_Values(xElement, ref _pasky);
}
}
}
private static void addItemsToVyplatnePasky2(IEnumerable<XElement> formattedAreaPairReport, List<VyplatnePasky> _pasky)
{
foreach (XElement xElement in formattedAreaPairReport.Elements("FormattedAreaPair".AddNamespace()))
{
VyplatnePasky _paska = new VyplatnePasky();
VyplatnePasky_Items(xElement, ref _paska);
_pasky.Add(_paska);
}
}
private static IEnumerable<XElement> tryToGetItemsFromDocument(string sPath, Func<XDocument, IEnumerable<XElement>> query, string name)
{
XDocument document = XDocument.Load(sPath);
var report = query(document);
if (report.Count() == 0)
{
//empty;
InsertErrorMessage("<formattedAreaPairReport> contains no data! No Data to parse from.", name);
}
return report;
}
本质上,您可以继续分解代码,然后寻找重复的习惯用法来清理。泛型可能会在清理过程中发挥作用,也可能不会。另外,您可能希望给这些方法起一个比我更好的名字,因为我不熟悉这段代码中使用的母语。: -)