使用 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()) {
    //???
}

使用 XmlReader 获取包含特定属性的每个节点的 XPath

感谢大家的反馈,我为我的解决方案使用了以下代码:

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函数。