【发布时间】:2021-12-09 13:31:03
【问题描述】:
我有一个包含大约 7000 个节点的 XML 文件(每行一个节点,没有级联节点),每个节点有大约 15 到 20 个保存十进制值的属性。 xml 文件大小约为 3 到 4 Mb。在每个节点中,符号属性都有唯一的值。
目标是通过匹配“符号”属性来搜索节点。
我有以下列出的方法,它将符号列表作为输入 (symbolList)。为了执行搜索,XPathDocument 从硬盘加载 XML 文件,对循环中的每个符号执行搜索,并以字典的形式返回结果。这些符号(输入)可以是 10 或 100 等(不固定)
为了执行搜索,我为每个符号运行了一个 for-each 循环。
问题:
(1) 搜索所有符号的另一种有效方法是什么? 一枪并删除一次搜索一个符号的循环。
在下面的代码中,我对效率不满意。 XPathNavigator 在循环中一次执行一个符号搜索,它检索匹配节点,读取属性值,并在集合中添加值。我想删除循环,它一次搜索一个符号。
我曾考虑通过添加所有带有“或”条件的符号来构建一个 XPath 查询,但是当我有 100 个左右的符号要搜索时,它可能是一个很大的 XPath 查询。有没有更好的解决方案来减少扫描次数?
(2) 如何利用 XPath 查询“编译”这个动态搜索?
我可以编译 XPath 查询来构建 XPathExpression,但这只有在我的 XPath 对多次扫描保持相同时才有用,而且我没有找到编译查询的方法,我可以将搜索 @parameter 值提供给编译的查询。有没有办法或任何例子来使用带参数的 Xslt 模板(作为字符串)?
(3) 还有什么其他建议可以减少 CPU 周期并使此代码比当前代码运行得更快吗?我并不是说这段代码很慢,但我想让它尽可能快。
Xml 文档示例:
<?xml version="1.0" encoding="utf-8"?>
<items>
<item symbol="ABC" val1="46.21717" val2="152.39" val3="158.121" />
<item symbol="CJKM" val1="51.21659" val2="49.8" val3="57.57" />
<item symbol="FWML" val1="67.99509" val2="9.75" val3="9.84" />
<item symbol="JSHR" val1="48.67459" val2="2.27" val3="2.9" />
<item symbol="DIBG" val1="53.60444" val2="26.04" val3="28" />
<item symbol="GHLH" val1="42.31754" val2="0.1016" val3="0.1192" />
<item symbol="ICWE" val1="58.39788" val2="3.855" val3="3.99" />
<item symbol="LPVN" val1="47.03581" val2="19.22" val3="20.15" />
<item symbol="MCAT" val1="57.83422" val2="23.0969" val3="26.59" />
<item symbol="ZYXI" val1="54.94584" val2="11.6784" val3="12.9" />
</items>
C# 代码:
using System.Collections.Generic;
using System.IO;
using System.Xml.XPath;
namespace Library
{
public class Info
{
public float Val1 { get; set; }
public float Val2 { get; set; }
public float Val2 { get; set; }
}
public class Technical
{
public Dictionary<string, Info> SearchForSymbols(HashSet<string> symbolList)
{
Dictionary<string, Info> dictSearchResult = new Dictionary<string, Info>();
if (symbolList.Count == 0)
{
return dictSearchResult;
}
FileInfo fileInfo = new FileInfo(Path.Combine(CommonObjects.Constant.SettingsFolderPath, CommonObjects.Constant.TechnicalFileName));
XPathDocument document = new XPathDocument(fileInfo.FullName);
XPathNavigator navigator = document.CreateNavigator();
string symbol;
float val1;
float val2;
float val3;
XPathNavigator node;
Info info;
foreach (string item in symbolList)
{
XPathExpression expression = navigator.Compile($"//items/item[@symbol='{item}']");
node = navigator.SelectSingleNode(expression);
if (node == null)
{
continue;
}
symbol = node.GetAttribute("symbol", "");
if (string.IsNullOrEmpty(symbol))
{
continue;
}
info = new Info();
// Get Value 1
if (float.TryParse(node.GetAttribute("val1", ""), out val1))
{
info.Val1 = val1;
}
// Get Value 2
if (float.TryParse(node.GetAttribute("val2", ""), out val2))
{
info.Val2 = val2;
}
// Get Value 3
if (float.TryParse(node.GetAttribute("val3", ""), out val3))
{
info.Val3 = val3;
}
if (!dictSearchResult.ContainsKey(symbol))
{
dictSearchResult.Add(symbol, info);
}
}
return dictSearchResult;
}
}
}
【问题讨论】:
-
你有没有先做任何性能指标?比较加载字典和比较使用 XPath 的时间。
标签: c# xml xpath xpathnavigator