我有一个XML示例:
<Fruits>
<Red_fruits>
<Red_fruits></Red_fruits>
</Red_fruits>
<Yellow_fruits>
<banana></banana>
</Yellow_fruits>
<Red_fruits>
<Red_fruits></Red_fruits>
</Red_fruits>
</Fruits>
我有4个Red_fruits标签,其中2个共享相同的ParentNode(Fruits),我想获得具有相同ParentNode的那些。
但我只想要那些名称相同的(Red_fruits),这意味着不包括Yellow_fruits标签。
这就是我现在使用C#语言的方式:
XmlDocument doc = new XmlDocument();
string selectedTag = cmbX.text;
if (File.Exists(txtFile.text))
{
try
{
//Load
doc.Load(cmbFile.text);
//Select Nodes
XmlNodeList selectedNodeList = doc.SelectNodes(".//" + selectedTag);
}
Catch
{
MessageBox.show("Some error message here");
}
}
这让我回到了所有red_fruits,而不仅仅是属于Fruit的那些。
我无法制作XmlNodeList = doc.SelectNodes(“/ Fruits / Red_fruits”),因为我想使用此代码来读取随机XML文件,因此我不知道特定节点将具有的确切名称,I只需要使用C#语言将所有具有相同名称和相同级别的节点放入XmlNodeList 。
有没有办法在不使用LINQ的情况下实现这一目标?怎么做?
答案 0 :(得分:8)
了解单斜杠/
和双斜杠//
的使用情况可以提供帮助。
让我们看看/
和//
如何与根节点相关联。在路径开头使用/
时:
/a
它将定义节点a
相对于根的绝对路径。因此,在这种情况下,它只会在XML树的根目录中找到a
个节点。
在路径开头使用//
时:
//a
它将在XML文档中的任何位置定义节点a
的路径。因此,在这种情况下,它将找到位于XML树中任意深度的a
个节点。
这些XPath表达式也可以在XPath值的中间用于定义祖先 - 后代关系。在路径中间使用/
时:
/a/b
它将定义节点b
的路径,该节点是节点a
的直接后代(即子节点)。
在路径中间使用//
时:
/a//b
它将定义节点b
的路径,该路径是节点a
的 ANY 后代。
回到你的问题:
//使用GetElementsByTagName()
返回所有名称为:Red_Fruits
XmlDocument doc = new XmlDocument();
XmlNodeList nodes= doc.GetElementsByTagName("Red_Fruits");
//使用SelectNodes()
方法
XmlNodelist nodes = doc.SelectNodes("//Fruits/Red_Fruits");
//这将选择<Fruits>
元素的子元素的所有元素。
如果<Fruits>
是根元素,请使用Xpath:/Fruits/Red_Fruits
。 [单斜杠/
]
答案 1 :(得分:3)
如果您只是想找到单个节点的“下一个”或“上一个”迭代,您可以执行以下操作,然后将其与名称进行比较
XmlNode current = doc.SelectSingleNode("Fruits").SelectSingleNode("Red_fruits");
XmlNode previous = current.NextSibling;
XmlNode next = current.NextSibling;
你可以迭代直到找到合适的兄弟
while(next.Name != current.Name)
{
next = next.NextSibling;
}
或者你甚至可以通过调用'Parent'属性来获取你的列表
XmlNodeList list = current.ParentNode.SelectNodes(current.Name);
答案 2 :(得分:1)
最糟糕的情况是,您可以遍历selectedNodeList中的XMLNode项并检查ParentNode属性。如有必要,您可以在ParentNode检查上递归,并计算到达根节点所需的次数。这将为您提供节点的深度。或者您可以比较每个级别的ParentNode,看看它是否是您感兴趣的父级,如果该父级不是根。
public void Test(){
XmlDocument doc = new XmlDocument();
string selectedTag = cmbX.text;
if (File.Exists(txtFile.text))
{
try
{
//Load
doc.Load(cmbFile.text);
//Select Nodes
XmlNodeList selectedNodeList = doc.SelectNodes(".//" + selectedTag);
List<XmlNode> result = new List<XmlNode>();
foreach(XmlNode node in selectedNodeList){
if(depth(node) == 2){
result.Add(node);
}
}
// result now has all the selected tags of depth 2
}
Catch
{
MessageBox.show("Some error message here");
}
}
}
private int depth(XmlNode node) {
int depth = 0;
XmlNode parent = node.ParentNode;
while(parent != null){
parent = node.ParentNode;
depth++;
}
return depth;
}