[英]C# Generic XML reader code
我有一個程序,該程序解析三個不同的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()));
但是它將變成一個大的混亂空間。
問題是-這實際上可行/值得嗎? 你能幫忙嗎?
您可以使用一些簡潔的編碼技術來使代碼干燥一些。 嘗試做這樣的事情:
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;
}
本質上,您可以繼續分解代碼,然后尋找重復的習慣用法進行清理。 在該清理過程中,泛型可能會起作用,也可能不會起作用。 另外,您可能想給這些方法命名比我更好的名稱,因為我不熟悉此代碼中使用的本機語言。 :-)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.