2016-02-10 48 views
0

我有一個可變的XML可能是這個樣子:使用XmlReader獲取包含特定屬性的每個節點的XPath?

<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> 

我想獲得的XPath爲所有具有屬性的「編輯」,等於「真」的節點。請注意,這些屬性可以在變量節點級別,因此我不能只遍歷一個級別的所有節點並檢查該屬性。由於速度的原因,我也想使用XmlReader,但如果有更好/更快的方法,那麼我也會接受。

var xml = IO.File.ReadAllText(contentFilePath); 
var readXML = XmlReader.Create(new StringReader(xml)); 

readXML.ReadToFollowing("content"); 

while (readXML.Read()) { 
    //??? 
} 
+2

如果你正在閱讀所有的文本到一個字符串,我認爲你失去了XmlReader的主要好處... – Jacob

+0

@Jacob嗯,這是很好的知道。如果文件位於文件系統上,最快的方法是什麼?讀取字節並提供流? – RichC

+1

@RichC你的文件有多大?性能優勢可以說是不值得的,除非它們非常大。 –

回答

0

感謝大家的反饋,我去與此代碼爲我的解決方案:

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); 
} 

I picked up the GetXPathToNode function from this thread

相關問題