首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XmlReader的c#空格问题

XmlReader的c#空格问题
EN

Stack Overflow用户
提问于 2012-02-23 01:25:38
回答 4查看 14.6K关注 0票数 6

我有一个简单的xml

代码语言:javascript
复制
<data>
    <node1>value1</node1>
    <node2>value2</node2>
</data>

我正在使用IXmlSerializable通过DTO来读写这样的xml。下面的代码运行良好

代码语言:javascript
复制
XmlReader reader;
...
while( reader.Read() ){
    Console.Write( reader.ReadElementContentAsString() );
}
// outputs value1value2

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

代码语言:javascript
复制
<data>
    <node1>value1</node1><node2>value2</node2>
</data>

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

这可能是XML解析器实现的错误吗?

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

下面是一个示例代码和两个产生不同结果的xml示例

代码语言:javascript
复制
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

代码语言:javascript
复制
<?xml version="1.0"?>
<data>
    <node-1>value1</node-1>
    <node-2>value2</node-2>
</data>

2.)settings.xml

代码语言:javascript
复制
<?xml version="1.0"?>
<data>
    <node-1>value1</node-1><node-2>value2</node-2>
</data>

使用(1)打印

代码语言:javascript
复制
Element node-1 value1
Element node-2 value2

使用(2)打印

代码语言:javascript
复制
Element node-1 value1
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-02-23 02:34:42

碰巧reader.Read()读取了空格字符。忽略空格,相同的指令读取第二个元素("gnam“一个XML标记),实际上将指针带到node2元素。

在示例中调用的方法之前和之后调试reader属性。检查NodeType和Value属性。也检查一下MoveToContent方法,它是非常有用的。

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

我最终采用了以下(不完整)模式:

代码语言:javascript
复制
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);
    }
}
票数 2
EN

Stack Overflow用户

发布于 2012-02-23 01:30:29

根据IgnoreWhitespace上的文档,新行并不是无关紧要的。

被认为不重要的

空白包括空格、制表符和空行,用于分隔标记以提高可读性。元素内容中的空白就是一个这样的例子。

XmlReaderSettings.IgnoreWhitespace

票数 3
EN

Stack Overflow用户

发布于 2014-04-08 09:25:15

这远没有Luca的答案那么健壮,但我发现下面的模式对合理的“可预测”XML很有用(只有空格和值的变化)。考虑一下:

代码语言:javascript
复制
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.Read(),然后使用reader.ReadContent*(),而不是使用reader.ReadElementContent*()

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9399850

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档