XmlReader的C#空格问题 [英] c# whitespaces issue with XmlReader

查看:40
本文介绍了XmlReader的C#空格问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的xml

I have a simple xml

<data>
    <node1>value1</node1>
    <node2>value2</node2>
</data>

我正在使用IXmlSerializable来使用DTO读写此类xml.以下代码可以正常工作

I'm using IXmlSerializable to read and write such xml with DTOs. The following code works just fine

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

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

However, if whitespaces in the xml are removed, i.e.

<data>
    <node1>value1</node1><node2>value2</node2>
</data>

或者我使用 XmlReaderSettings.IgnoreWhitespace = true; ,该代码仅输出"value1",而忽略了第二个节点.当我打印解析器遍历的节点时,我可以看到 ReadElementContentAsString 将指针移到了 node2 EndElement ,但是我没有了解为什么会发生这种情况或如何解决它.

or I use XmlReaderSettings.IgnoreWhitespace = true;, the code outputs only "value1" ignoring the second node. When I print the nodes that the parser traverses, I can see that ReadElementContentAsString moves the pointer to the EndElement of node2, but I don't understand why that should be happening or how to fix it.

是否可能是XML解析器实现错误?

Is it a possible XML parser implementation bug?

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

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

这是一个示例代码和2个xml示例,它们会产生不同的结果

Here's a sample code and 2 xml samples that produce different results

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

1.) settings.xml

<?xml version="1.0"?>
<data>
    <node-1>value1</node-1>
    <node-2>value2</node-2>
</data>

2.)settings.xml

2.) settings.xml

<?xml version="1.0"?>
<data>
    <node-1>value1</node-1><node-2>value2</node-2>
</data>

使用(1)张照片

Element node-1 value1
Element node-2 value2

使用(2)张照片

Element node-1 value1

推荐答案

发生 reader.Read()读取空白字符的情况.忽略空格,同一条指令将读取第二个元素(XML令牌"gnam"),实际上是将指针带到 node2 元素.

It happens that reader.Read() read the white space character. Ignoring the spaces, the same same instruction read the second element ("gnam" a XML token), indeed bringing the pointer to the node2 element.

调试 reader 属性.检查 NodeType Value 属性.还请检查一下 MoveToContent 方法,它非常有用.

Debug the reader properties before and after the methods called in you example. Check for NodeType and Value properties. Give also a check for MoveToContent method also, it is very useful.

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

Read the documentation of all that methods and properties, and you will end up to learn how XmlReader class works, and how you use it for your purposes. Here is the first google result: it contains a very explicit example.

我最终遇到以下(未完成)模式:

I ended up to the following (not complete) pattern:

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);
    }
}

这篇关于XmlReader的C#空格问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆