How to Use SelectNodes in C # To filter XML elements

Source: Internet
Author: User

Some strange phenomena occurred when SelectNodes was used in C # today. Let's start by restoring the site.
First, create a simple XML file to test, or save it as test. xml.
 
<? Xml version = "1.0" encoding = "UTF-8"?>
<Root>
<Users job = "salas">
<User>
<Name> Joe </name>
<Age> 17 </age>
</User>
<User>
<Name> Kate </name>
<Age> 12 </age>
</User>
<User>
<Name> Parry </name>
<Age> 66 </age>
</User>
<User>
<Name> Qiqi </name>
<Age> 32 </age>
</User>
</Users>
<Users job = "developer">
<User>
<Name> David </name>
<Age> 23 </age>
</User>
<User>
<Name> Eath </name>
<Age> 54 </age>
</User>
</Users>
</Root>
 
 
Below is my C # code
 
Static void Main (string [] args)
{
XmlDocument doc = new XmlDocument ();
Doc. Load ("test. xml ");

XmlElement root = doc. DocumentElement;
XmlNode userCollection = root. SelectSingleNode ("users [1]");
XmlNodeList usersOfOne = userCollection. SelectNodes ("user ");


XmlNode placeholder = doc. CreateElement ("placeholder ");
Channel. ReplaceChild (placeholder, usersOfOne. Item (0 ));

Console. WriteLine (usersOfOne. Count );

}
 
 
The Code logic is simple. You just need to find the first <users> node and replace it with the first <user> subnode.
The key lies in the problem after replacement. I originally thought that the number of usersOfOne should be 4 <user> nodes, but the final result is only 1, it's just the replaced node.
 
Continue the test. This time, modify the C # code and change the replaced node to the second <user> node. How can this problem be solved? The number of usersOfOne becomes two, including the first and second nodes.
Study SelectNodes source code (the following source code is viewed in Reflector 6)
 
Public XmlNodeList SelectNodes (string xpath)
{
XPathNavigator navigator = this. CreateNavigator ();
If (navigator = null)
{
Return null;
}
Return new XPathNodeList (navigator. Select (xpath ));
}
 
 
It returns an XPathNodeList, and then looks at its constructor.
Public XPathNodeList (XPathNodeIterator nodeIterator)
{
This. nodeIterator = nodeIterator;
This. list = new List <XmlNode> ();
This. done = false;
}
 
You will find that it creates a List <XmlNode> but does not assign a value to it. Let's look at the Count attribute again.
 
Public override int Count
{
Get
{
If (! This. done)
{
This. ReadUntil (0x7fffffff );
}
Return this. list. Count;
}
}
 
 
It returns the Count of the List <XmlNode> created in the constructor. Let's look at the function Item ().
 
Public override XmlNode Item (int index)
{
If (this. list. Count <= index)
{
This. ReadUntil (index );
}
If (index> = 0) & (this. list. Count> index ))
{
Return this. list [index];
}
Return null;
}
 
 
The value in the returned List <XmlNode> is the same.
Therefore, we can explain the strange phenomena in the above experiment code.
When SelectNodes is used, it does not actually extract the node, but when we call other methods (such as the item () or Count attribute ), the value is saved to the List <XmlNode> using ReadUntil.
The Count attribute can save 0x7fffffff nodes (this also implies the maximum number of nodes that can be processed !?), The Item function only saves the number you need (you can also look at the ReadUntil method). Because I replaced the current node, it cannot find the next node through iteration. Therefore, when replacing the second node, it only retains the reason for the first second node.
The above code is modified as follows:
 
Static void Main (string [] args)
{
XmlDocument doc = new XmlDocument ();
Doc. Load ("test. xml ");

XmlElement root = doc. DocumentElement;
XmlNode channel = root. SelectSingleNode ("users [1]");
XmlNodeList usersOfOne = channel. SelectNodes ("user ");

// Call Count immediately after SelectNodes
Console. WriteLine (usersOfOne. Count );


XmlNode placeholder = doc. CreateElement ("placeholder ");
Channel. ReplaceChild (placeholder, usersOfOne. Item (0 ));

Console. WriteLine (usersOfOne. Count );

}
 
 
It will print the results as I expected. After the node is replaced, the output is still 4.
This problem is hard to be found during debugging, because you can view usersOfOne during debugging. the Count attribute is equivalent to the execution of the Count attribute in the source program. Therefore, when debugging a program, the output result is also 4, which leads to different performance during running and debugging.

 

 

From Volkswagen. NET

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.