使用 XmlReader 获取包含特定属性的每个节点的 XPath
本文关键字:节点 XPath 属性 XmlReader 获取 包含特 使用 | 更新日期: 2023-09-27 18:34:02
我有一个变量XML,可能看起来像这样:
<content>
<main editable="true">
<h1>Here is my header</h1>
<p>Here is my content</p>
</main>
<buttons>
<positive editable="true">I agree!</positive>
<negative editable="true">No - get me outta here!</negative>
</button>
</content>
我想获取所有具有等于"true"属性"可编辑"的节点的 XPath。 请注意,属性可以位于可变节点级别,因此我不能只在一个级别遍历所有节点并检查属性。 由于速度,我也想使用 XmlReader,但如果有更好/更快的方法,那么我也对此持开放态度。
var xml = IO.File.ReadAllText(contentFilePath);
var readXML = XmlReader.Create(new StringReader(xml));
readXML.ReadToFollowing("content");
while (readXML.Read()) {
//???
}
感谢大家的反馈,我为我的解决方案使用了以下代码:
Dim xml = IO.File.ReadAllText(masterLangDir)
Dim xdoc = New XmlDocument()
xdoc.LoadXml(xml)
Dim xPaths = findAllNodes(xdoc.SelectSingleNode("content"), New List(Of String))
public List<string> findAllNodes(XmlNode node, List<string> xPaths)
{
foreach (XmlNode n in node.ChildNodes) {
var checkForChildNodes = true;
if (n.Attributes != null) {
if (n.Attributes("editable") != null) {
if (n.Attributes("editable").Value == "true") {
xPaths.Add(GetXPathToNode(n));
checkForChildNodes = false;
}
}
}
if (checkForChildNodes) {
xPaths = findAllNodes(n, xPaths);
}
}
return xPaths;
}
public string GetXPathToNode(XmlNode node)
{
if (node.NodeType == XmlNodeType.Attribute) {
// attributes have an OwnerElement, not a ParentNode; also they have
// to be matched by name, not found by position
return String.Format("{0}/@{1}", GetXPathToNode(((XmlAttribute)node).OwnerElement), node.Name);
}
if (node.ParentNode == null) {
// the only node with no parent is the root node, which has no path
return "";
}
// Get the Index
int indexInParent = 1;
XmlNode siblingNode = node.PreviousSibling;
// Loop thru all Siblings
while (siblingNode != null) {
// Increase the Index if the Sibling has the same Name
if (siblingNode.Name == node.Name) {
indexInParent += 1;
}
siblingNode = siblingNode.PreviousSibling;
}
// the path to a node is the path to its parent, plus "/node()[n]", where n is its position among its siblings.
return String.Format("{0}/{1}[{2}]", GetXPathToNode(node.ParentNode), node.Name, indexInParent);
}
我从这个线程中选择了GetXPathToNode函数。