XmlReader方括号导致读者进入错误状态

时间:2009-11-02 14:15:56

标签: c# .net xml xml-serialization

我有一个试图将文本读入元素列表的XmlReader。我在阅读文本时遇到了麻烦:“a [z]”。如果我尝试使用文本“a [z]”(相同但有两个尾随空格),它可以正常工作。以下是一个例子:

TextReader tr = new StringReader("a [ z ]");
XmlReaderSettings settings = new XmlReaderSettings
{
    ConformanceLevel = ConformanceLevel.Fragment,
    ProhibitDtd = false,
    ValidationType = ValidationType.None,
    XmlResolver = null,
    CheckCharacters = false,
    IgnoreProcessingInstructions = true,
};
XmlReader reader = XmlReader.Create(tr, settings);
reader.Read();

StringBuilder sb = new StringBuilder();

while (!reader.EOF)
{
    if (reader.NodeType == XmlNodeType.Text || reader.NodeType == XmlNodeType.Whitespace)
    {
        sb.Append(reader.Value);
        reader.Read();
    }   
}

// sb.ToString() should be "a [ z ]"

运行时失败并显示以下消息:“System.Xml.XmlException:发生了意外的文件结束。第1行,第7位。”和堆栈跟踪:

at System.Xml.XmlTextReaderImpl.Throw(Exception e) 
at System.Xml.XmlTextReaderImpl.ParseText(Int32& startPos, Int32& endPos, Int32& outOrChars)
at System.Xml.XmlTextReaderImpl.FinishPartialValue()
at System.Xml.XmlTextReaderImpl.get_Value()
at LocalisationFormats.Tests.Shared.InlineElements.InlineElementHelperTest.Test()

当您尝试调试它时,Reader的ReadState为“Error”,而Reader.Value为“a [z”,然后您打破阅读器并获得OutOfMemoryExecption。

有人有什么建议吗?

编辑:根据Gregoire的建议从代码段中移除额外的if。

3 个答案:

答案 0 :(得分:2)

我认为问题在于,当您将非Xml格式的字符串加载到XmlReader对象中时。

“XmlReader提供对XML数据流的只进,只读访问.XmlReader类符合W3C可扩展标记语言(XML)1.0和XML推荐中的命名空间。” &安培; “XmlReader在XML解析错误上抛出XmlException。” - MSDN XmlReader类文章http://msdn.microsoft.com/en-us/library/system.xml.xmlreader.aspx

尝试通过更改:

来加载和读取实际的Xml数据

TextReader tr = new StringReader("a [ z ]");

为:

TextReader tr = new StringReader("<node>a [ z ]</node>");

或者,如果您需要在自己的节点中每个部分:

TextReader tr = new StringReader("<node>a</node><node> </node><node>[</node><node> </node><node>z</node><node> </node><node>]</node>");

我正在为后一个例子提供完整的资源,因为我认为这就是你的目标。

TextReader tr = new StringReader("<node>a</node><node> </node><node>[</node><node> </node><node>z</node><node> </node><node>]</node>");
XmlReaderSettings settings = new XmlReaderSettings
{
    ConformanceLevel = ConformanceLevel.Fragment,
    ProhibitDtd = false,
    ValidationType = ValidationType.None,
    XmlResolver = null,
    CheckCharacters = false,
    IgnoreProcessingInstructions = true,
};
XmlReader reader = XmlReader.Create(tr, settings);
reader.Read();

StringBuilder sb = new StringBuilder();

while (!reader.EOF)
{
    string s = reader.ReadElementString();

    if (s != " ")
    {
        sb.Append(s);
    }
}

这将允许您遍历节点,获取完整的字符串值,没有例外。

〜的md5sum〜

答案 1 :(得分:0)

我已经检查过这个问题已经在.Net 4中得到修复,但截至本文帖子仍然在.Net 3.5中被破解。

答案 2 :(得分:0)

很抱歉疏通了一个有三年之久的问题,但我遇到了同样的问题。对于未来的任何googlers:

看起来OP和微软的人提出了这个问题 - connect.microsoft.com/VisualStudio/feedback

  

感谢您报告此问题。我们已经在.NET 4.0中解决了这个问题。我们不打算在以前版本的.NET中修复它。升级到.NET 4.0将解决此问题。

     

谢谢,   Arun Chandrasekhar,   高级项目经理,   XML团队

对于我们这些仍然坚持使用.Net&lt; 4.0(在我的情况下是2.0)我用这个可怕的黑客来解决这个问题:

const string openSquareBracketReplacement = "##OSB##";
const string closeSquareBracketReplacement = "##CSB##";

xml = xml
    .Replace("[", openSquareBracketReplacement)
    .Replace("]", closeSquareBracketReplacement);

// Build an XmlReader and use it.

return xml
    .Replace(openSquareBracketReplacement, "[")
    .Replace(closeSquareBracketReplacement, "]");

显然这会完全打破CDATA处理,但这对我来说是可以的。