2

I have an xml like this:

<People>
  <PersonID>5</PersonID>
  <PersonID>7</PersonID>
  <PersonID>9</PersonID>
</People>

I would like to create a string with all the id's, like this: "5,7,9". I know it's possible with a simple loop, but since this code will be called 100's of time a second, I would like to make it the fastest possible way.

I'm using C# framework 4.0.

My current code:

XmlDocument doc = new XmlDocument();
XmlNodeList nodeList;
StringBuilder strXml = new StringBuilder();
doc.LoadXml(sXmlQuery);
nodeList = doc.SelectNodes("//PersonID");
if (nodeList != null)
{
    foreach (XmlNode node in nodeList)
    {
        strXml.Append(node.InnerText.Trim());
        strXml.Append(",");
    }
}
Stephan
  • 41,764
  • 65
  • 238
  • 329
Itay.B
  • 3,991
  • 14
  • 61
  • 96
  • Show your code so that we can suggest some improvements.. – I4V May 07 '13 at 07:53
  • try with Linq to Xml? – alfdev May 07 '13 at 07:54
  • alfdev - can you provide an example? – Itay.B May 07 '13 at 07:55
  • or XPath? http://stackoverflow.com/questions/5279786/performance-of-xpath-vs-dom - Michael Kay Answer is really good, in a Point of View between XPath and DOM – Smartis has left SO again May 07 '13 at 07:56
  • 1
    I'd argue your code is close to the fastest approach already. Only suggestion I can make is to create the `StringBuilder` within the body of the `if`, so that no StringBuilder is made if there is no node set. Also the string inside the StringBuilder will end in a comma. You'd need to strip the last comma off. – Bazzz May 07 '13 at 08:13

3 Answers3

4

You can use LINQ to XML with string.Join like:

XDocument xmlDoc = XDocument.Parse(@"<People>
                                      <PersonID>5</PersonID>
                                      <PersonID>7</PersonID>
                                      <PersonID>9</PersonID>
                                    </People>");
var val = xmlDoc.Descendants("People")
                 .SelectMany(r => r.Elements("PersonID"))
                 .Select(r => r.Value);
string str = string.Join(",", val);

str will be str = "5,7,9"

Habib
  • 219,104
  • 29
  • 407
  • 436
  • 1
    This looks like a good approach however, I'm not sure it's faster than the code in the OP. Do you have an empirical proof that your code is significantly faster? – Bazzz May 07 '13 at 08:10
  • @Bazzz, No I don't. First version of the question didn't have the code lines to compare with, I think OP can measure the performance using `Stopwatch` for both the codes. – Habib May 07 '13 at 08:47
  • Habib, please note that no offence was intended from my side, and your code is perfectly valid. I just noticed that the OP was asking explicitly for a performance increase and I was only pointing out that likely your code is not faster than the code that the OP added later. Your suggestion using `Stopwatch` might be a good way to find the fastest approach. – Bazzz May 07 '13 at 09:01
  • Thank you both Habib and Bazzz for your help. – Itay.B May 07 '13 at 09:24
  • @Bazzz, I didn't take any offence :), I'm sorry, if I sounded rude – Habib May 07 '13 at 09:29
1

I don't know it is fast enough for you but I'll give it a try

string s = String.Join("," , xDoc.Descendants("PersonID").Select(p => (string)p));
EZI
  • 15,209
  • 2
  • 27
  • 33
0

Try the following code:

 public DataTable GetColumnsFromXML(String XMLPath, String TableName)
{
    DataTable dtForColumns = DatatableforColumns();
    XmlDataDocument xmldoc = new XmlDataDocument();
    xmldoc.Load(XMLPath);
    XmlElement root = xmldoc.DocumentElement;
    XmlNodeList tablenodes = root.SelectNodes("Table");

    if (tablenodes != null)

        foreach (XmlNode nodes in tablenodes)
        {
            if (!nodes.HasChildNodes) continue;
            if (nodes.Attributes == null) continue;
            //TableName = nodes.Attributes[0].Value;

            if (nodes.Attributes[0].Value == TableName)
            {
                String PrimaryKey = nodes.Attributes[1].Value;
                var nodesdisplayname = nodes.SelectNodes("Column/DisplayColumn");
                var nodesorignalvalue = nodes.SelectNodes("Column/OrignalColumn");

                if (nodesdisplayname != null && nodesorignalvalue != null)
                {
                    for (int i = 0; i <= nodesdisplayname.Count - 1; i++)
                    {
                        var xmlDisplayNode = nodesdisplayname.Item(i);
                        var xmlOrignalNode = nodesorignalvalue.Item(i);


                        if (xmlDisplayNode != null && xmlOrignalNode != null)
                        {

                            DataRow dr;
                            dr = dtForColumns.NewRow();
                            dr["DisplayColumn"] = xmlDisplayNode.InnerText;
                            dr["OrignalColumn"] = xmlOrignalNode.InnerText;
                            dr["PrimaryKey"] = PrimaryKey;
                            dtForColumns.Rows.Add(dr);
                        }
                    }
                }
            }
        }
    return dtForColumns;
}
private DataTable DatatableforColumns()
{
    DataTable dt = new DataTable();
    dt.Columns.Add("DisplayColumn", typeof(String));
    dt.Columns.Add("OrignalColumn", typeof(String));
    dt.Columns.Add("PrimaryKey", typeof(String));
    return dt;
}

To Access these here is the code:

DataTable dtColumns = new DataTable();        
dtColumns = objXML.GetColumnsFromXML(Server.MapPath("~/XMLFile.xml"), TableName);

Customize it according to your requirement, hope this will work for you.

Ram Singh
  • 6,664
  • 35
  • 100
  • 166