使用XmlReader类使用相同名称的元素解析XML

时间:2012-11-30 09:48:58

标签: c# xml xmlreader

我正在重写一些使用XmlDocument来解析某些XML的代码。我想使用XmlReader来查看是否可以获得一些性能改进。 XML的结构如下所示:

<items>
   <item id="1" desc="one">
      <itemBody date="2012-11-12" />
   </item>
   <item id="2" desc="two">
      <itemBody date="2012-11-13" />
   </item>
   <item id="3" desc="three">
      <itemBody date="2012-11-14" />
   </item>
   <item id="4" desc="four">
      <itemBody date="2012-11-15" />
   </item>
</items>

基本上,我需要遍历所有<item>元素。就像我说的那样,旧代码的工作原理如下:

XmlDocument document = new XmlDocument();

// load XML into XmlDocument
document.LoadXml(xml);

// use xpath to split into individual item
string xPath = @"items/item";
XmlNodeList nodeList = document.SelectNodes(xPath);

// loop through each item
for (int nodeIndex = 0; nodeIndex < nodeList.Count; nodeIndex++)
{
    // do something with the XmlNode
    nodeList[nodeIndex];
}

这很好用,但我认为使用XmlReader会更快。所以我写了这个:

XmlReader xmlReader = XmlReader.Create(new StringReader(xml));

while (xmlReader.Read())
{                       
   if (xmlReader.Name.Equals("item") && (xmlReader.NodeType == XmlNodeType.Element))
   {
      string id = xmlReader.GetAttribute("id");                 
      string desc = xmlReader.GetAttribute("desc");
      string elementXml = xmlReader.ReadOuterXml();
   }
}

但是,此代码仅读取第一个<item>元素。 ReadOuterXml()打破了循环。有谁知道怎么解决这个问题?或者XmlReader无法进行这种类型的解析?我必须使用.NET版本2执行此操作:(所以我不能使用LINQ。

3 个答案:

答案 0 :(得分:4)

刚刚在LinqPad中测试了您的代码。效果很好。

 var xml = @"<items>
   <item id='1' desc='one' />
   <item id='2' desc='two' />
   <item id='3' desc='three' />
   <item id='4' desc='four' />
</items>";
XmlReader xmlReader = XmlReader.Create(new StringReader(xml));

while (xmlReader.Read())
{   
   if (xmlReader.Name.Equals("item") && (xmlReader.NodeType == XmlNodeType.Element))
   {
      string id = xmlReader.GetAttribute("id");              
      string desc = xmlReader.GetAttribute("desc");
      Console.WriteLine("{0} {1}", id, desc);
   }
}

输出:

1 one
2 two
3 three
4 four

您的XML可能存在问题。

答案 1 :(得分:1)

以下似乎有效: -

        StringBuilder xml = new StringBuilder();

        xml.Append("<items>");
        xml.Append("<item id=\"1\" desc=\"one\">");
        xml.Append("<itembody id=\"10\"/>");
        xml.Append("</item>");
        xml.Append("<item id=\"2\" desc=\"two\">");
        xml.Append("<itembody id=\"20\"/>");
        xml.Append("</item>");
        xml.Append("<item id=\"3\" desc=\"three\">");
        xml.Append("<itembody id=\"30\"/>");
        xml.Append("</item>");
        xml.Append("</items>");

        using (XmlTextReader tr = new XmlTextReader(new StringReader(xml.ToString())))
        {
            bool canRead = tr.Read();
            while (canRead)
            {
                if ((tr.Name == "item") && tr.IsStartElement())
                {
                    Console.WriteLine(tr.GetAttribute("id"));
                    Console.WriteLine(tr.GetAttribute("desc"));
                    string outerxml = tr.ReadOuterXml();
                    Console.WriteLine(outerxml);

                    canRead = (outerxml != string.Empty);
                }
                else
                {
                    canRead = tr.Read();
                }
            }
        }

答案 2 :(得分:0)

如果你可以使用Linq,这是另一种方法:

class Program
{
    static void Main(string[] args)
    {

        const string xml = @"<items>
                          <item id='1' desc='one'>
                            <itemBody date='2012-11-12' />
                          </item>
                          <item id='2' desc='two'>
                            <itemBody date='2012-11-13' />
                          </item>
                          <item id='3' desc='three'>
                            <itemBody date='2012-11-14' />
                          </item>
                          <item id='4' desc='four'>
                            <itemBody date='2012-11-15' />
                          </item>
                        </items>";

        var xmlReader = XmlReader.Create(new StringReader(xml));

        XElement element = XElement.Load(xmlReader, LoadOptions.SetBaseUri);

        IEnumerable<XElement> items = element.DescendantsAndSelf("item");

        foreach (var xElement in items)
        {
            string id = GetAttributeValue("id", xElement);
            string desc = GetAttributeValue("desc", xElement);
            string itemBody = GetElementValue("itemBody", "date", xElement);

            Console.WriteLine("id = {0}, desc = {1}, date = {2}", id, desc, itemBody);
        }

        Console.ReadLine();
    }

    private static string GetElementValue(string elementName, string attributeName, XElement element)
    {
        XElement xElement = element.Element(elementName);

        string value = string.Empty;

        if (xElement != null)
        {
            XAttribute xAttribute = xElement.Attribute(attributeName);

            if (xAttribute != null)
            {
                value = xAttribute.Value;
            }
        }

        return value;
    }

    private static string GetAttributeValue(string attributeName, XElement element)
    {
        XAttribute xAttribute = element.Attribute(attributeName);

        string value = string.Empty;
        if (xAttribute != null)
        {
            value = xAttribute.Value;
        }

        return value;
    }
}