c#whitespaces与XmlReader有关

我有一个简单的xml

 value1 value2  

我正在使用IXmlSerializable来读取和编写带有DTO的xml。 以下代码工作得很好

 XmlReader reader; ... while( reader.Read() ){ Console.Write( reader.ReadElementContentAsString() ); } // outputs value1value2 

但是,如果xml中的空格被删除,即

  value1value2  

或者我使用XmlReaderSettings.IgnoreWhitespace = true; ,代码只输出“value1”忽略第二个节点。 当我打印解析器遍历的节点时,我可以看到ReadElementContentAsString将指针移动到node2EndElement ,但我不明白为什么会发生这种情况或如何解决它。

它是一个可能的XML解析器实现错误吗?

===============================================

这是一个示例代码和2 xml样本,可以产生不同的结果

 string homedir = Path.GetDirectoryName(Application.ExecutablePath); string xml = Path.Combine( homedir, "settings.xml" ); FileStream stream = new FileStream( xml, FileMode.Open ); XmlReaderSettings readerSettings = new XmlReaderSettings(); readerSettings.IgnoreWhitespace = false; XmlReader reader = XmlTextReader.Create( stream, readerSettings ); while( reader.Read() ){ if ( reader.MoveToContent() == XmlNodeType.Element && reader.Name != "data" ){ System.Diagnostics.Trace.WriteLine( reader.NodeType + " " + reader.Name + " " + reader.ReadElementContentAsString() ); } } stream.Close(); 

1.)settings.xml

   value1 value2  

2.)settings.xml

   value1value2  

使用(1)打印

 Element node-1 value1 Element node-2 value2 

使用(2)打印

 Element node-1 value1 

它发生在reader.Read()读取空格字符。 忽略空格,相同的指令读取第二个元素(“gnam”一个XML标记),确实将指针带到node2元素。

在示例中调用的方法之前和之后调试reader属性。 检查NodeTypeValue属性。 还要检查MoveToContent方法,它非常有用。

阅读所有方法和属性的文档,最后您将了解XmlReader类的工作原理,以及如何将它用于您的目的。 这是第一个谷歌结果:它包含一个非常明确的例子。

我最终得到以下(不完整)模式:

 private static void ReadXmlExt(XmlReader xmlReader, IXmlSerializableExt xmlSerializable, ReadElementDelegate readElementCallback) { bool isEmpty; if (xmlReader == null) throw new ArgumentNullException("xmlReader"); if (readElementCallback == null) throw new ArgumentNullException("readElementCallback"); // Empty element? isEmpty = xmlReader.IsEmptyElement; // Decode attributes if ((xmlReader.HasAttributes == true) && (xmlSerializable != null)) xmlSerializable.ReadAttributes(xmlReader); // Read the root start element xmlReader.ReadStartElement(); // Decode elements if (isEmpty == false) { do { // Read document till next element xmlReader.MoveToContent(); if (xmlReader.NodeType == XmlNodeType.Element) { string elementName = xmlReader.LocalName; // Empty element? isEmpty = xmlReader.IsEmptyElement; // Decode child element readElementCallback(xmlReader); xmlReader.MoveToContent(); // Read the child end element (not empty) if (isEmpty == false) { // Delegate check: it has to reach and end element if (xmlReader.NodeType != XmlNodeType.EndElement) throw new InvalidOperationException(String.Format("not reached the end element")); // Delegate check: the end element shall correspond to the start element before delegate if (xmlReader.LocalName != elementName) throw new InvalidOperationException(String.Format("not reached the relative end element of {0}", elementName)); // Child end element xmlReader.ReadEndElement(); } } else if (xmlReader.NodeType == XmlNodeType.Text) { if (xmlSerializable != null) { // Interface xmlSerializable.ReadText(xmlReader); Debug.Assert(xmlReader.NodeType != XmlNodeType.Text, "IXmlSerializableExt.ReadText shall read the text"); } else xmlReader.Skip(); // Skip text } } while (xmlReader.NodeType != XmlNodeType.EndElement); } } 

根据IgnoreWhitespace的文档,新行不被认为是无关紧要的。

不被视为重要的空格包括空格,制表符和用于分隔标记以获得更高可读性的空行。 一个例子是元素内容中的空格。

XmlReaderSettings.IgnoreWhitespace

这并不像Luca的回答那么强大,但我发现以下模式对于合理的“可预测的”XML(仅限空格和值的变化)很有用。 考虑:

 string homedir = Path.GetDirectoryName(Application.ExecutablePath); string xml = Path.Combine( homedir, "settings.xml" ); FileStream stream = new FileStream( xml, FileMode.Open ); XmlReaderSettings readerSettings = new XmlReaderSettings(); readerSettings.IgnoreWhitespace = false; XmlReader reader = XmlTextReader.Create( stream, readerSettings ); while( reader.Read() ){ if ( reader.MoveToContent() == XmlNodeType.Element && reader.Name != "data" ){ string name = reader.Name; string value = null; if (!reader.IsEmptyElement) { reader.Read(); // advances reader to element content value = reader.ReadContentAsString(); // advances reader to endelement } reader.Read(); // advance reader to element content System.Diagnostics.Trace.WriteLine( reader.NodeType + " " + name + " " + value ); } } stream.Close(); 

更一般地,代替reader.ReadElementContent*() ,使用reader.Read()后跟reader.ReadContent*()

如果您希望XmlReader不读取空格,则应使用以下设置初始化XmlReader:

 XmlReaderSettings settings = new XmlReaderSettings(); settings.IgnoreWhitespace = true; XmlReader xrd = XmlReader.Create(@"file.xml", settings); 

它适用于我发布的结构的xml文件:

  value1 value2