【问题标题】:Handling shorthand closing tag while parsing XML在解析 XML 时处理速记结束标记
【发布时间】:2012-08-06 19:26:03
【问题描述】:

为了简单起见,我将大大降低项目的复杂性,并给出一个简单但同样准确的例子来说明我正在努力解决的问题。我有两个 XML 文件,我们将它们命名为 Read.xmlWrite.xml。目标是让我的项目读取 Read.xml 的内容,将 XML 解析为一个类,然后将其重建为 Write.xml

XML 生成到 Read.xml 的方式是,当元素没有值时,它使用速记结束标记 (<ElementName />),而当它有值时,它使用普通结束标签 (<ElementName>Element Value</ElementName>)。我无法控制 Read.xml 中 XML 的生成。

下面的代码非常适合解析 XML,只要它使用普通结束标记。但是,如果说下面的ReportId 有速记结束标记,那么现在的代码将读取下一行(对于长手写结束标记,这将是 XML 元素的值),但下一行是值为 "\n" 的空白元素。然后,这会在 Write.xml 中的 XML 中添加一个新行,这会使 XML 格式变得奇怪。这是我用来从 Read.xml 读取和解析 XML 的代码:

        while(xmlReader.Read())
        {
            switch(xmlReader.NodeType)
            {
                case XmlNodeType.Element:
                    if(xmlReader.Name.Equals("ReportSummary") && xmlReader.IsStartElement())
                    {
                        currentReport = new Entities.Report();
                    }
                    else if(xmlReader.Name.Equals("ReportName"))
                    {
                        xmlReader.Read();
                        currentReport.ReportName = xmlReader.Value;
                    }
                    else if(xmlReader.Name.Equals("ReportId"))
                    {
                        xmlReader.Read();
                        currentReport.ReportId = xmlReader.Value;
                    }
                    break;
                case XmlNodeType.EndElement: //Reached the end of the element.
                    if(xmlReader.Name.Equals("ReportSummary"))
                    {
                        if(currentReport!= null)
                        {
                            reportList.Add(currentReport);
                            currentReport = null;
                        }
                    }
                    break;
                default:
                    break;
            }
        }

我的问题是,是否有适当的方法来处理速记结束标签与长手结束标签。或者,有没有更好的方法来解析一个 XML 文件?

提前感谢大家提供的任何内容。

【问题讨论】:

  • 任何合适的 XML 解析器都应该能够毫无障碍地处理自闭合标签。我认为 SAX 对它们没有任何问题。
  • 您的 XML 有多大?是否值得使用阅读器,或者您可以使用更高级别的 api 解析?
  • 如果您正在处理巨大的 Xml 文档,我建议您阅读我在数据库转储中使用过的这个有趣的技术:blogs.msdn.com/b/xmlteam/archive/2007/03/24/…
  • 关于为工作选择正确 API 的说明:blogs.msdn.com/b/xmlteam/archive/2011/09/14/…

标签: c# xml xml-parsing


【解决方案1】:

您可以使用XmlReader.IsEmptyElement 来确定阅读器是否在一个空元素处:http://msdn.microsoft.com/en-us/library/system.xml.xmlreader.isemptyelement.aspx

【讨论】:

  • 感谢韦恩,这暂时是一个足够简单的修复。并感谢其他所有人的意见。当我有更多的时间来改进这部分时,我会回到这里来获得一些想法。非常感谢。
【解决方案2】:

如果可能,您可以使用 LINQ to XML...

认为它会让你的一切变得更简单。

http://msdn.microsoft.com/en-us/library/bb387098.aspx

希望对你有帮助...

【讨论】:

    【解决方案3】:


    如果您倾向于采用一种性能稍差但更易于管理的方式, 我会建议一个类似于以下的解决方案:

        XmlDocument xmlDoc = new XmlDocument();
        List<Entities.Report> reports = new List<Entities.Report>();
        xmlDoc.Load("Read.xml");
        foreach (XmlNode reportNode in xmlDoc.SelectNodes("//ReportSummary"))
        {
            Entities.Report report = new Entities.Report();
            report.ReportName = reportNode["ReportName"].InnerText;
            report.ReportId = reportNode["ReportId"].InnerText;
            reports.Add(report);
        }
    

    更具可读性、可维护性且性能稍差。
    祝你好运!

    【讨论】:

      【解决方案4】:

      我会使用 XmlDocument 的 SelectSingleNode 函数,它在解析文件时会更有效率。

      http://msdn.microsoft.com/en-us/library/system.xml.xmlnode.selectsinglenode.aspx

      如果有多个节点,可以使用 SelectNodes 函数。

      http://msdn.microsoft.com/en-us/library/4bektfx9.aspx

      正如 spender 所指出的,您还可以使用 XDocument/XElement 对其进行解析。如果您至少使用框架 3.5,则此方法可能更可取

      【讨论】:

      • 哪种方式效率更高?现在解析 XML 的首选方法是使用 Linq 和 XDocument/XElement。相比之下,XmlDocument 显得笨拙。
      • XDocument/XElement 也很好,我将它与使用 switch 和 if 语句进行比较,如问题所示。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-06-16
      • 1970-01-01
      • 1970-01-01
      • 2015-01-11
      • 2014-01-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多