C#:如何根据 child 元素的属性过滤 XML 文件的结果?
C#: How can I filter the results of an XML file based on a child element's attribute?
我可能可以更好地措辞标题,但我正在冒险进入我以前从未涉足的编程领域,所以我仍在学习术语。但这是我正在尝试做的事情:
我正在编写一个可以对螺栓接头进行结构分析的程序。但是,我不想让用户每次都输入螺栓几何形状,而是希望他们可以从 ASME 统一螺纹标准 (UTS) 尺寸的标准列表中选择 select。所以我创建了一个 Bolt class,然后是一个 UTSBolt subclass。我正在为 UTS 螺栓尺寸制作一个 XML 文件。到目前为止,我可以 de-serialize XML 文件,将它投影到我的 UTSBolts class 的 IEnumerable 中,让用户 select 一个螺栓,一切都是 hunky-dory.
但这是我的问题...
UTS 尺寸将指定螺栓的直径以及 coarse-thread (UNC) 和 fine-thread (UNF) 螺栓的螺纹密度。因此,我将我的 XML 文件格式化为:
<Bolts_UTS>
<Bolt>
<Size>#0</Size>
<MajorDiameter>0.0600</MajorDiameter>
<ThreadDensity Series="UNF">80</ThreadDensity>
</Bolt>
<Bolt>
<Size>#1</Size>
<MajorDiameter>0.0730</MajorDiameter>
<ThreadDensity Series="UNC">64</ThreadDensity>
<ThreadDensity Series="UNF">72</ThreadDensity>
</Bolt>
<Bolt>
<Size>#2</Size>
<MajorDiameter>0.0860</MajorDiameter>
<ThreadDensity Series="UNC">56</ThreadDensity>
<ThreadDensity Series="UNF">64</ThreadDensity>
</Bolt>
<Bolt>
<Size>#3</Size>
<MajorDiameter>0.0990</MajorDiameter>
<ThreadDensity Series="UNC">48</ThreadDensity>
<ThreadDensity Series="UNF">56</ThreadDensity>
</Bolt>
<Bolt>
<Size>#4</Size>
<MajorDiameter>0.1120</MajorDiameter>
<ThreadDensity Series="UNC">40</ThreadDensity>
<ThreadDensity Series="UNF">48</ThreadDensity>
</Bolt>
</Bolts_UTS>
当用户 select 螺栓尺寸时,我希望他们也能够 select 螺纹系列 (UNC/UNF)。但我似乎无法弄清楚如何正确设置过滤器以仅读取 Series 属性为 "UNF" 的 ThreadDensity。无论属性如何,我的程序总是获取第一个 ThreadDensity 值。
有人可以帮我弄清楚我做错了什么吗?这是我的代码:
static void Main(string[] args)
{
string pathCurrent = Directory.GetCurrentDirectory();
string pathToXML = Path.GetFullPath(Path.Combine(pathCurrent, "Bolts_UTS.xml"));
XElement boltsUTS = XElement.Load(pathToXML);
IEnumerable<UTSBolt> boltList =
from el in boltsUTS.Elements("Bolt")
where (
from thread in el.Elements("ThreadDensity")
where
(string)thread.Attribute("Series") == "UNF"
select thread).Any() &&
((string)el.Element("Size") == "#1")
select new UTSBolt(
(string)el.Element("Size"),
(double)el.Element("MajorDiameter"),
(double)el.Element("ThreadDensity")
);
Console.WriteLine(" | Major |");
Console.WriteLine("UN Size\t| Dia. (inch) | Thr. / In.");
Console.WriteLine("--------|-------------|------------");
foreach (UTSBolt bolt in boltList)
Console.WriteLine(bolt);
Console.ReadLine();
}
输出:
| Major |
UN Size | Dia. (inch) | Thr. / In.
--------|-------------|------------
#1 | 0.07300 | 64
您只查看此 子查询 中的 Series
属性:
where (
from thread in el.Elements("ThreadDensity")
where
(string)thread.Attribute("Series") == "UNF"
select thread).Any() &&
((string)el.Element("Size") == "#1")
这只是检查 ThreadDensity
元素在 el
中是否有正确的系列。
您实际 创建 UTSBolt
的代码只是获取第一个 ThreadDensity
元素:
select new UTSBolt(
(string)el.Element("Size"),
(double)el.Element("MajorDiameter"),
(double)el.Element("ThreadDensity")
);
我怀疑你想要这样的东西:
var boltList =
from el in boltsUTS.Elements("Bolt")
let thread = el.Elements("ThreadDensity")
.FirstOrDefault(t => (string) t.Attribute("Series") == "UNF")
let size = (string) el.Element("Size")
where thread != null && size == "#1"
select new UTSBolt(size, (double) el.Element("MajorDiameter"), (double) thread);
我可能可以更好地措辞标题,但我正在冒险进入我以前从未涉足的编程领域,所以我仍在学习术语。但这是我正在尝试做的事情:
我正在编写一个可以对螺栓接头进行结构分析的程序。但是,我不想让用户每次都输入螺栓几何形状,而是希望他们可以从 ASME 统一螺纹标准 (UTS) 尺寸的标准列表中选择 select。所以我创建了一个 Bolt class,然后是一个 UTSBolt subclass。我正在为 UTS 螺栓尺寸制作一个 XML 文件。到目前为止,我可以 de-serialize XML 文件,将它投影到我的 UTSBolts class 的 IEnumerable 中,让用户 select 一个螺栓,一切都是 hunky-dory.
但这是我的问题...
UTS 尺寸将指定螺栓的直径以及 coarse-thread (UNC) 和 fine-thread (UNF) 螺栓的螺纹密度。因此,我将我的 XML 文件格式化为:
<Bolts_UTS>
<Bolt>
<Size>#0</Size>
<MajorDiameter>0.0600</MajorDiameter>
<ThreadDensity Series="UNF">80</ThreadDensity>
</Bolt>
<Bolt>
<Size>#1</Size>
<MajorDiameter>0.0730</MajorDiameter>
<ThreadDensity Series="UNC">64</ThreadDensity>
<ThreadDensity Series="UNF">72</ThreadDensity>
</Bolt>
<Bolt>
<Size>#2</Size>
<MajorDiameter>0.0860</MajorDiameter>
<ThreadDensity Series="UNC">56</ThreadDensity>
<ThreadDensity Series="UNF">64</ThreadDensity>
</Bolt>
<Bolt>
<Size>#3</Size>
<MajorDiameter>0.0990</MajorDiameter>
<ThreadDensity Series="UNC">48</ThreadDensity>
<ThreadDensity Series="UNF">56</ThreadDensity>
</Bolt>
<Bolt>
<Size>#4</Size>
<MajorDiameter>0.1120</MajorDiameter>
<ThreadDensity Series="UNC">40</ThreadDensity>
<ThreadDensity Series="UNF">48</ThreadDensity>
</Bolt>
</Bolts_UTS>
当用户 select 螺栓尺寸时,我希望他们也能够 select 螺纹系列 (UNC/UNF)。但我似乎无法弄清楚如何正确设置过滤器以仅读取 Series 属性为 "UNF" 的 ThreadDensity。无论属性如何,我的程序总是获取第一个 ThreadDensity 值。
有人可以帮我弄清楚我做错了什么吗?这是我的代码:
static void Main(string[] args)
{
string pathCurrent = Directory.GetCurrentDirectory();
string pathToXML = Path.GetFullPath(Path.Combine(pathCurrent, "Bolts_UTS.xml"));
XElement boltsUTS = XElement.Load(pathToXML);
IEnumerable<UTSBolt> boltList =
from el in boltsUTS.Elements("Bolt")
where (
from thread in el.Elements("ThreadDensity")
where
(string)thread.Attribute("Series") == "UNF"
select thread).Any() &&
((string)el.Element("Size") == "#1")
select new UTSBolt(
(string)el.Element("Size"),
(double)el.Element("MajorDiameter"),
(double)el.Element("ThreadDensity")
);
Console.WriteLine(" | Major |");
Console.WriteLine("UN Size\t| Dia. (inch) | Thr. / In.");
Console.WriteLine("--------|-------------|------------");
foreach (UTSBolt bolt in boltList)
Console.WriteLine(bolt);
Console.ReadLine();
}
输出:
| Major |
UN Size | Dia. (inch) | Thr. / In.
--------|-------------|------------
#1 | 0.07300 | 64
您只查看此 子查询 中的 Series
属性:
where (
from thread in el.Elements("ThreadDensity")
where
(string)thread.Attribute("Series") == "UNF"
select thread).Any() &&
((string)el.Element("Size") == "#1")
这只是检查 ThreadDensity
元素在 el
中是否有正确的系列。
您实际 创建 UTSBolt
的代码只是获取第一个 ThreadDensity
元素:
select new UTSBolt(
(string)el.Element("Size"),
(double)el.Element("MajorDiameter"),
(double)el.Element("ThreadDensity")
);
我怀疑你想要这样的东西:
var boltList =
from el in boltsUTS.Elements("Bolt")
let thread = el.Elements("ThreadDensity")
.FirstOrDefault(t => (string) t.Attribute("Series") == "UNF")
let size = (string) el.Element("Size")
where thread != null && size == "#1"
select new UTSBolt(size, (double) el.Element("MajorDiameter"), (double) thread);