【问题标题】:Using XmlReader how do I read past an empty element?使用 XmlReader 如何读取空元素?
【发布时间】:2016-07-21 15:55:39
【问题描述】:

我使用 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 文件。这就是它中断的地方。它可以很好地读取元素、元素 1、元素 2 和元素 3。但是,当它到达 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. 如何修复并继续跳过此问题,以便我可以阅读其余元素。

【问题讨论】:

  • 1) 您能否尝试将您的问题简化为minimal reproducible example?它相当复杂但也不完整,因为我们不能只是复制/粘贴到 Visual Studio 中并运行。 2) 你签出stackoverflow.com/questions/279534/…
  • 抱歉,我已经尽可能简化了。我已经排除了我用来读写 xml 文件的测试方法。我想到了。我在下面为任何感兴趣的人提供了一个解决方案。大问题的简单解决方案。

标签: c# xml xmlreader


【解决方案1】:

当我从我的 xml 文件中读取我的元素时,我需要添加另一个 else if 条件来处理,如果元素是开始元素并且元素是空的。我只是检查它是否不是空的。所以它不知道如何处理它是空的。然后,当满足这些条件时,我只需要执行 reader.Read() 来告诉应用程序按&lt;element4/&gt; 读取元素。

这是它的样子:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-08
    • 2014-05-31
    • 2013-07-30
    • 2023-01-10
    • 1970-01-01
    • 2016-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多