使用 XmlReader 如何读取空元素?

Using XmlReader how do I read past an empty element?

我使用 XmlWriter 编写了一个 Xml 文件。 这是代码:

public void WriteXml(XmlWriter writer)
        {
            writer.WriteStartElement("element1");
            writer.WriteAttributeString("attrs1", Attrs1);
            writer.WriteAttributeString("attrs2", Attrs2);

            if (!string.IsNullOrWhiteSpace("element2"))
            {
                writer.WriteStartElement("element2");
                writer.WriteCData(Element2);
                writer.WriteEndElement();
            }
            if (!string.IsNullOrWhiteSpace("element3"))
            {
                writer.WriteStartElement("element3");
                writer.WriteCData(Element3);
                writer.WriteEndElement();
            }
            Element4.WriteXml(writer);
            Element5.WriteXml(writer);

            writer.WriteEndElement();            
        }

如您所见,element4 调用了一个名为 "WriteXml()" 的方法。这是该方法:

public void WriteXml(XmlWriter writer)
        {
            if (m_PropertyValueList.Count > 0)
            {
                writer.WriteStartElement("element4");

                foreach (var p in m_PropertyValueList)
                {
                    if (p.CurrentValue != null)
                    {
                        writer.WriteStartElement("property");
                        writer.WriteAttributeString("name", p.PropertyName);
                        writer.WriteAttributeString("value", p.CurrentValue.ToString());
                        writer.WriteEndElement();
                    }
                }    
                writer.WriteEndElement();
            }
        }

请注意,它会检查 p.CurrentValue != null。如果它为空,那么这个元素应该被写成一个空元素。在本例中,p.CurrentValue 为空,因此我确实需要一个空元素。您将在下面的 Xml 输出中看到将此元素写为 .对我来说,它看起来像是在正确地写一个空元素,如果我在这里错了,请纠正我。

Xml 文件输出如下所示:

<?xml version="1.0" encoding="UTF-8"?>

-<element>   
    -<element 1 attrs1="Some Info" attrs2="More Info">   
        -<element2>    
            +<![CDATA[]]>
        </element2>   
        -<element3>    
            -<![CDATA[ ]]>
        </element3>    
        <element4/>    
    </element1>    
</element>

然后我创建了一个方法来读取 Xml 文件。这就是它中断的地方。它可以很好地读取 element、element1、element2 和 element3。但是,当涉及到 element4 时,我开始遇到问题。我将在下面解释。

这里是 XmlReader 方法:

public void ReadXml(XmlReader reader)
        {
            if (reader.IsStartElement("element1"))
            {
                //
                // Get the values of all the <element1> attributes
                //
                Attrs1= reader.GetAttribute("attrs1");
                Attrs2 = reader.GetAttribute("attrs2");

                //
                // Read past <element1>
                //
                reader.Read();

                while (true)
                {
                    if (reader.IsStartElement("element2"))
                    {
                        Description = reader.ReadElementContentAsString();
                    }
                    else if (reader.IsStartElement("element3"))
                    {
                        Source = reader.ReadElementContentAsString();
                    }
                    else if (reader.IsStartElement("element4")) && (!reader.IsEmptyElement))
                    {
                        Element4.ReadXml(reader);
                    }
                    else if ((reader.IsStartElement("element5")) && (!reader.IsEmptyElement))
                    {
                        Element5.ReadXml(reader);
                    }
                    else
                    {
                        reader.MoveToContent();
                        reader.ReadEndElement();
                        break;
                    }
                }
            }
            else
            {
                throw new XmlException("Expected <element1> element was not present");
            }
        }

请注意,如果 element4 IsStartElement 并且它不是空元素,它将调用 Element4.ReadXml()。这是该方法:

public void ReadXml(XmlReader reader)
        {
            if ((reader.IsStartElement("element4")) && (!reader.IsEmptyElement))
            {
                reader.Read();

                while (reader.IsStartElement("property"))
                {
                    string propertyName = reader.GetAttribute("name");
                    string propertyValue = reader.GetAttribute("value");
                    SetValue(propertyName, propertyValue);
                    reader.Read();
                }

                //
                //  Read </element4>
                //
                reader.MoveToContent();
                reader.ReadEndElement();
            }            
        }

但是由于 element4 是空的,因此永远不会调用此方法。所以它将继续到 else{} 语句并在到达 reader.ReadEndElement() 时中断;我收到的错误消息是:

"Message: TestMethod myTestMethodName threw exception: System.Xml.XmlException 'Element' is an invalid XmlNodeType. Line 8, position 6."  

所以我的问题是:

  1. 这是因为元素是空的吗?如果是这样,我如何关闭或读取空元素?
  2. 如果 element4 是开始元素并且它不为空,那么我正在读取它的位置....如果我删除 (!reader.IsEmptyElement) 我会得到一个无限循环。它继续调用 Element4.ReadXml(reader)。为什么是这样?
  3. 如何解决并继续解决这个问题,以便我可以阅读其余元素。

在我从 xml 文件中读取元素的地方,我需要添加另一个 else if 条件来处理元素是否为起始元素以及元素是否为空。我只是在检查它是否不是空的。所以它不知道如何处理它是空的。然后,当满足这些条件时,我只需执行 reader.Read() 即可告诉应用程序按原样读取元素 <element4/>

这是它的样子:

else if (reader.IsStartElement("element4")) && (reader.IsEmptyElement))
    {
        reader.Read();
    }