初級 .NET C# 自學者在這里。今天我“迷失”了一天,試圖圍繞 XPath、XPath 運算式、XPathDocument、XPathNodeIterator 和 XPathNavigator。我想我一定是做錯了什么,因為我無法相信從 XML 檔案中獲取名稱、值和屬性會如此困難。
我只需幾行代碼,不到 10 分鐘就可以在 PowerShell 中實作我的預期目標。然而,這花了我一整天的時間,我仍然感到完全失落。
有人可以通過以下方式提供幫助:
- 確認我在正確的路線上并且沒有做一些完全瘋狂的事情。
- 告訴我是否有更簡單的方法可以做到這一點。
- 幫助我獲取缺失的值/屬性。
這是我的 XML 檔案:https ://gist.github.com/arbitmcdonald/3c5381e920fac7b880df68912bfddbd9
我們感興趣的資料(來自上面的鏈接檔案)是這些壞男孩:
<cdf:rule-result severity="medium" weight="10.0" time="2022-05-28T23:12:16" version="DTBI014-IE11" idref="xccdf_mil.disa.stig_rule_SV-59337r8_rule">
<cdf:result>fail</cdf:result>
<cdf:ident system="http://iase.disa.mil/cci">CCI-002450</cdf:ident>
<cdf:fix id="F-50263r18_fix"></cdf:fix>
<cdf:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
<cdf:check-content-ref href="#scap_mil.disa.stig_comp_U_MS_IE11_V1R16_STIG_SCAP_1-2_Benchmark-oval.xml" name="oval:mil.disa.fso.ie:def:580"></cdf:check-content-ref>
</cdf:check>
</cdf:rule-result>
目前,使用上面的 XML 片段,我得到以下輸出(每次迭代):
severity = medium
weight = 10.0
time = 2022-05-28T23:12:16
version = DTBI014-IE11
idref = xccdf_mil.disa.stig_rule_SV-59337r8_rule
cdf:rule-result = failCCI-002450
我想要得到的是:
severity = medium
weight = 10.0
time = 2022-05-28T23:12:16
version = DTBI014-IE11
idref = xccdf_mil.disa.stig_rule_SV-59337r8_rule
result = fail
checkIdentifier = CCI-002450
fixId = F-50263r18_fix
checkSchema = http://oval.mitre.org/XMLSchema/oval-definitions-5
checkName = oval:mil.disa.fso.ie:def:580
到目前為止,這是我的游樂場/學習代碼:
void Main()
{
// This is shared above
string path = @"C:\tmp\Example.xml";
XPathNavigator nav;
XPathDocument docNav;
XPathNodeIterator NodeIter;
String strExpression;
// Open the XML.
docNav = new XPathDocument(path);
// Create a navigator to query with XPath.
nav = docNav.CreateNavigator();
strExpression = "/cdf:Benchmark/cdf:TestResult/cdf:rule-result";
var nsmgr = new XmlNamespaceManager(nav.NameTable);
nsmgr.AddNamespace("cdf", "http://checklists.nist.gov/xccdf/1.2");
// Select the node and place the results in an iterator.
NodeIter = nav.Select(strExpression, nsmgr);
while (NodeIter.MoveNext())
{
XPathNavigator navigator2 = NodeIter.Current.Clone();
navigator2.MoveToFirstAttribute();
Console.WriteLine("{0} = {1}", navigator2.Name, navigator2.Value);
while (navigator2.MoveToNextAttribute())
{
Console.WriteLine("{0} = {1}", navigator2.Name, navigator2.Value);
}
Console.WriteLine("{0} = {1}", NodeIter.Current.Name, NodeIter.Current.Value);
Console.WriteLine();
}
}
提前感謝任何指示,要么我做錯了,要么這是我在.NET中做過的最艱難的事情之一......
uj5u.com熱心網友回復:
看起來您正在遍歷節點的屬性<cdf:rule-result>,而不是子節點的屬性。我已經XPathNavigator很長時間沒有使用了,但我建議研究一下
XPathNavigator.SelectChildren和XPathNavigator.SelectDescendants方法。
uj5u.com熱心網友回復:
我不會亂用 C# 代碼來做這些,我會在一個 XSLT 3.0 樣式表中完成所有這些作業:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0" expand-text="yes" xmlns:cdf=""http://checklists.nist.gov/xccdf/1.2">
<xsl:output method="text"/>
<xsl:template match="/">
severity = {cdf:rule-result/@severity}
weight = {cdf:rule-result/@weight}
time = {cdf:rule-result/@time}
version = {cdf:rule-result/@version}
idref = {cdf:rule-result/@idref}
result = {cdf:rule-result/@severity}
checkIdentifier = {cdf:rule-result/@cdf:ident}
fixId = {cdf:rule-result/cdf:fix/@id}
checkSchema = {cdf:rule-result/cdf:check/@system}
checkName = {cdf:rule-result/cdf:check-content-ref/@name}
</xsl:template>
</xsl:transform>
如果您更喜歡使用 Microsoft 處理器,那么在 XSLT 1.0 中這并不困難 - 只需將花括號中的內容替換為<xsl:value-of select="..."/>
uj5u.com熱心網友回復:
如果您想使用 XPath 1.0,您至少可以這樣做
foreach (XPathNavigator result in nav.Select(strExpression, nsmgr))
{
foreach (XPathNavigator value in result.Select(".//@* | .//*[normalize-space()]", nsmgr))
{
Console.WriteLine("{0} = {1}", value.LocalName, value.Value);
}
Console.WriteLine();
}
這將收集您顯示的所有資料以及樣本中的兩三個資料,但您想要的輸出未顯示;顯然,它不會重命名。目前尚不清楚需要哪些值,哪些不需要,所以到目前為止我還沒有嘗試在 XPath 中排除值。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/482863.html
上一篇:xml資料中串列的一項
