【问题标题】:Getting the name of an XML document's root node获取 XML 文档根节点的名称
【发布时间】:2015-08-23 00:13:44
【问题描述】:

我有一个要加载的 XML 文件。我想在我的代码中添加一个条件来检查并确保根节点是“TimeLog”。如果不是,则告诉用户他们选择了错误的 XML 文件。

在下面的代码中,r.Name 只返回一个空字符串。我希望它返回“TimeLog”,但事实并非如此。

    private void loadFromFile(object sender, EventArgs e)
    {
        if(File.Exists("TimeLog.xml"))
        {
            XmlReader r = XmlReader.Create("TimeLog.xml");
            r.MoveToContent();
            r.ReadStartElement();
            if (r.Name == "TimeLog") //The current value or r.name is "".
            {
                while (r.Read())
                {
                    if (r.NodeType == XmlNodeType.Element)
                    {
                        r.ReadToDescendant("EntryName");
                        String name = r.ReadInnerXml();
                        r.ReadToFollowing("StartDateTime");
                        String start = r.ReadInnerXml();
                        r.ReadToFollowing("EndDateTime");
                        String end = r.ReadInnerXml();
                        r.ReadToFollowing("Duration");
                        String dur = r.ReadInnerXml();

                        entries.Add(new Entry(name, start, end, dur));
                    }
                }
            }
            else
            {
                MessageBox.Show("This is not a TimeLog XML file", "This is not a TimeLog XML file", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
            }
            r.Close();
        }
    }

XML 文件是我的 saveToFile() 函数的输出,如下所示

<?xml version="1.0" encoding="utf-8"?>
<TimeLog>
    <Entry>
        <EntryName>Entry 01</EntryName>
        <StartDateTime>8/21/2015 8:50:40 PM</StartDateTime>
        <EndDateTime>1/1/0001 12:00:00 AM</EndDateTime>
        <Duration>00:00:00</Duration>
    </Entry>
    <Entry>
        <EntryName>Entry 02</EntryName>
        <StartDateTime>8/21/2015 8:50:40 PM</StartDateTime>
        <EndDateTime>1/1/0001 12:00:00 AM</EndDateTime>
        <Duration>00:00:00</Duration>
    </Entry>
</TimeLog>

如何检查以确保根节点的名称是“TimeLog”,而无需调用另一个 .Read() 函数并取消 while 语句中代码的顺序?

【问题讨论】:

    标签: c# xml xmlreader


    【解决方案1】:

    ReadStartElement方法说明:

    检查当前节点是否是一个元素并将阅读器推进到 下一个节点。

    下一个节点是XmlNodeType.Whitespace


    考虑以下 XML:

    <TimeLog>
        <Entry>
    

    也可以写成:

    <TimeLog>    <Entry>
    

    两个XmlNodeType.Element之间有XmlNodeType.Whitespace

    MoveToContent 将 reader 设置为根节点 - TimeLog。然后ReadStartElement 读取 TimeLog 并移动到空白处。


    以下视图中没有空格:

    <TimeLog><Entry>
    

    顺便说一句,你可以使用ReadToFollowing 方法:

    using (var reader = XmlReader.Create("file.xml"))
    {
        reader.ReadToFollowing("TimeLog");
        // rest of code
    }
    

    【讨论】:

    • 我还是 XML 新手,为什么下一个节点会是 Whitespace?我认识的唯一空白是标签之间的文本。
    • 我没有意识到缩进字符实际上会被读取,我认为空格会被忽略。谢谢。
    【解决方案2】:

    尝试实现以下代码,如果仍有错误,请告诉我:

    if(File.Exists("TimeLog.xml"))
        {
            XmlReader r = XmlReader.Create("TimeLog.xml");
            r.MoveToContent();
      //Here check whether there exist a root element and then also check itsname.
      //If this doesn't work out then put the r.Name=="TimeLog" inside While loop and then see.
    
        if (r.IsStartElement() && string.Equals(r.Name, "TimeLog"))
            {
                while (r.Read())
                {
                    if (r.NodeType == XmlNodeType.Element)
                    {
                        r.ReadToDescendant("EntryName");
                        String name = r.ReadInnerXml();
                        r.ReadToFollowing("StartDateTime");
                        String start = r.ReadInnerXml();
                        r.ReadToFollowing("EndDateTime");
                        String end = r.ReadInnerXml();
                        r.ReadToFollowing("Duration");
                        String dur = r.ReadInnerXml();
    
                        entries.Add(new Entry(name, start, end, dur));
                    }//End of inner If
                }//End of While
            }//End of Outer second IF
            else
            {
                MessageBox.Show("This is not a TimeLog XML file", "This is not a TimeLog XML file", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
            }//End of Else
            r.Close();
    

    【讨论】:

    • 谢谢。这与我现有的代码完美配合。
    • @Bill.. 很高兴听到这个消息。
    【解决方案3】:

    如果您可以使用 LINQ to XML,请查看XDocument.Root.Name

    XDocument doc = XDocument.Load("TimeLog.xml");
    
    if (doc.Root.Name == "TimeLog")
    {
        // ...
    }
    else
    {
        MessageBox.Show("This is not a TimeLog XML file", "This is not a TimeLog XML file", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
    }
    

    【讨论】:

      【解决方案4】:

      使用以下代码可以很快找到根元素。通过使用 XmlReader 而不是 XmlDocument,不必将整个文档加载到内存中。

        if (File.Exists("TimeLog.xml"))
        {
          XmlReader r = XmlReader.Create("TimeLog.xml");
          while (reader.Read() && reader.NodeType != XmlNodeType.Element) ;
          // r is now referencing the node for the root element.
        }
      

      有效 XML 文档中的根 节点 是一个 XML 声明,这可能不是您想要的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-18
        • 2012-03-06
        • 1970-01-01
        • 1970-01-01
        • 2011-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多