简体   繁体   中英

Searching XML in C#

I have an xml that I want to search and return a child node in C#.

For example

<STOCK>
   <STOCKNAME name="Microsoft">     
      <STOCKSYMBOL>MSFT</STOCKSYMBOL>
   </STOCKNAME>
   <STOCKNAME name="Apple Inc.">        
       <STOCKSYMBOL>AAPL</STOCKSYMBOL>
   </STOCKNAME>
   <STOCKNAME name="Google">        
       <STOCKSYMBOL>GOOG</STOCKSYMBOL>
   </STOCKNAME> 
</STOCK>

If I pass the string Microsoft, I want to get a return of MSFT only. I think Im doing this wrong

String stockText = "";
XmlTextReader reader = new XmlTextReader(@"C:\xml\stockname2.xml");

while (reader.Read())
{
    switch (reader.NodeType)
    {
        case XmlNodeType.Element:
             break;

        case XmlNodeType.Text:
             if (reader.GetAttribute("name") == stock) 
             {
                stockText = reader.GetAttribute("symbol");
             }
             break;
    }
}

Thank you in advance.

I wouldn't call it "wrong" because you could make that work, but it is definitely not the best approach. You would in essence be re-writing something called XPath which is built into the .net framework (and is a W3C spec supported by many parsers)

You can reduce your code to something like:

var doc = new XmlDocument();
doc.Load(@"C:\xml\stockname2.xml");

var node = doc.SelectSingleNode("//STOCK/STOCKNAME[@name = 'Microsoft']/STOCKSYMBOL");
string symbol = node.InnerText; // this should be "MSFT"

The best way to "search XML" is to use XPath and/or XQuery. This is fully supported in C# (and all .Net languages).

Here are some examples:

Using Linq2Xml

string searchFor="Microsoft";
XDocument xDoc = XDocument.Load(.....);

var result =  xDoc.Descendants("STOCKNAME")
    .Where(x=>x.Attribute("name").Value==searchFor)
    .Select(x=>x.Element("STOCKSYMBOL").Value)
    .SingleOrDefault();

I agree with the other posters that XPath and a document-oriented approach is the better way to go, but for the purposes of understanding the code you have written, here we go:

When you hit the Element that matches the company you're looking for, you then want to advance to the Text node and get its value. Something like this:

    while (reader.Read())
    {
        switch (reader.NodeType)
        {
            case XmlNodeType.Element:
                if (reader.GetAttribute("name") == stock)
                {
                    if (reader.Read() && reader.NodeType == XmlNodeType.Text)
                    {
                        stockText = reader.Value;
                    }
                }
                break;
        }
    }

(Apologies for any Javaisms that have crept into my C#.)

The reason that I prefer document-oriented solutions is that you can load the XML once and query it many times (for many stocks, in your case). With an XmlTextReader, you get just one pass through the file.

It's probably not very robust, but I would do something as simple as this:

String stock = "Microsoft";
String stockText = "";
XmlTextReader reader = new XmlTextReader(@"C:\xml\stockname2.xml");

while(reader.ReadToFollowing("STOCKNAME"))
{
    if(reader.GetAttribute("name") == stock)
    {
        reader.ReadToDescendant("STOCKSYMBOL");
        stockText = reader.ReadElementContentAsString();
        break;
    }
}

As long as your XML doesn't vary much it should work fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM