假设我有以下 xml(一个简单的示例)
<rows>
<row>
<name>one</name>
</row>
<row>
<name>two</name>
</row>
</rows>
我尝试使用 XmlDocument 和 XPath 来解析它(最终我可以制作一个行列表)。
例如...
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
foreach(XmlNode row in doc.SelectNodes("//row"))
{
string rowName = row.SelectSingleNode("//name").InnerText;
}
为什么在我的 foreach 循环中, rowName 始终为“一”?我希望第一次迭代时它是“一”,第二次迭代时是“二”。
//name 似乎获取了文档中的第一个实例,而不是我所期望的行中的第一个实例。毕竟,我是在“行”节点上调用该方法。如果这就是“它是如何工作的”,那么任何人都可以解释一下我如何改变它以满足我的需要吗?
谢谢你
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
foreach(XmlNode row in doc.SelectNodes("//row"))
{
var rowName = row.SelectSingleNode("name");
}
您发布的代码真的正确吗?我在 row.SelectNode() 上遇到编译错误,因为它不是 XmlNode 的成员。
无论如何,我上面的示例是有效的,但假设
<name>
节点中只有一个 <row>
节点,因此如果情况并非如此,您可能需要使用 SelectNodes()
而不是 SelectSingleNode()
。
正如其他人所示,使用
.InnerText
即可获取值。
使用 LINQ to XML。在您的代码文件中包含
using System.Xml.Linq;
,然后执行以下代码来获取您的列表
XDocument xDoc = XDocument.Load(filepath);
IEnumerable<XElement> xNames;
xNames = xDoc.Descendants("name");
这将为您提供名称元素的列表。然后如果你想把它变成
List<string>
只需这样做:
List<string> list = new List<string>();
foreach (XElement element in xNames)
{
list.Add(element.value);
}
您的第二个 xpath 以
//
开头。这是 /descendant-or-self::node()
的缩写,您可以看到它以 /
开头,这意味着它会从文档的根目录搜索,无论您在什么上下文中使用它。
您可能想要以下之一:
var rowName = row.SelectSingleNode("name");
找到作为
name
的 直接子节点 的 row
节点,或者
var rowName = row.SelectSingleNode(".//name");
在第二个 xpath 中的
name
rowthe
.` 下找到 . Note the
节点*任意位置,这会导致 xpath 从上下文节点开始。
使用相对路径,例如
string rowName = row.SelectSingleNode("name").InnerText;
。
问题出在您的第二个 XPath 查询中:
//row
它具有全局作用域,因此无论您从哪里调用它,它都会选择 all
row
元素。
如果将表达式替换为:
,应该会起作用.//row
我将使用 SelectSingleNode,然后使用 InnerText 属性。
var rowName = row.SelectSingleNode("name").InnerText;
使用以下内容
doc.LoadXml(xml);
foreach(XmlNode row in doc.SelectNodes("/rows/row"))
{
string rowName = row.SelectSingleNode("//name").InnerText.ToString();
}
下面以 XML 为例,使用 XPath 获取文档数据
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE svg (View Source for full doctype...)> <!-- Created with AIM. --> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1668.75 1074.75" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" zoomAndPan="magnify" version="1.0" contentScriptType="text/ecmascript" contentStyleType="text/css"> can't read ": no such element in array <g id="#1" class="track" /> <g id="#5" class="dedication"> <metadata> <meta name="color">Red</meta> </metadata> <text fill="#181818">AQWSD</text> </g> <g id="#6" class="wordasword"> <metadata> <meta name="epigraph">Output 1</meta> <meta name="color">Red</meta> <meta name="refentry">qandadiv</meta> </metadata> <paramdef fill="none" /> <text fill="#181818">0.35</text> </g> <g id="#7" class="wordasword"> <metadata> <meta name="epigraph">Output 2</meta> <meta name="color">Red</meta> <meta name="refentry">calloutlist</meta> <meta name="screen">common></meta> </metadata> <path fill="none" /> <text fill="#181818">lineannotation</text> <text fill="#181818">WHO</text> <paramdef fill="#232323" /> </g> <g id="#" class="wordasword"> <metadata> <meta name="epigraph">Output 3</meta> <meta name="color">Red</meta> <meta name="refentry">calloutlist</meta> <meta name="screen">common></meta> </metadata> <path fill="none" /> <text fill="#181818">lineannotation</text> <text fill="#181818">WHO</text> <paramdef fill="#232323" /> </g> </svg>
我已经检查并构建了下面运行正常的代码。下面是上述 XML 文档的运行时值 xmlContent
var xmlContent =“
红色
XmlDocument xml = new XmlDocument();
xml.LoadXml(xmlContent);
//Select all g Nodes of class wordasword that have color red in metadata>meta
var gNodesOnClassOfColorRed = xml.SelectNodes("//*[local-name()='g'][@class='wordasword'][*[local-name()='metadata'][*[local-name()='meta'][@name='color'] = 'Red']]").Cast<XmlNode>();
foreach (XmlNode gNode in gNodesOnClassOfColorRed)
{
var metadata = gNode.SelectSingleNode("*[local-name()='metadata']").Cast<XmlNode>(); //Fetch metadata of g tag
//Fetch epigraph value from meta tag from metadata
var epigraph = metadata.Cast<XmlNode>()
.Where(z => z.Attributes.Count != 0 && z.Attributes.GetNamedItem("name") != null && z.Attributes.GetNamedItem("name").Value.Trim().ToLower() == "epigraph")
.Select(p => p.InnerText).FirstOrDefault();
Console.WriteLine(epigraph);
}
铭文值的输出将打印为
输出1、输出2、输出3