XmlReader 创建空字符串 C#

XmlReader creates empty string C#

我正在使用 StringReader 读取 xml 流,然后我想将该流读取为 XML 以对其进行序列化和反序列化。 尽管由于某种原因它工作正常,但我的 XmlReader 变量 returns null。 我看到的XML和之前一样

我的代码是:

  StringReader stringReader = new StringReader(result);
        stringReader.ReadLine();//omit the first line that contains xml encoding
        XmlReader xmlReader = XmlReader.Create(stringReader);
        XmlSerializer XmlSerializer = new XmlSerializer(typeof(ResponseDoc));
        ResponseDoc XmlResponseDoc = (ResponseDoc)XmlSerializer.Deserialize(xmlReader);

结果变量的XML格式是

    <?xml version="1.0" encoding="utf-8"?>
<ResponseDoc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <response>
    <entitylineNumber>1</entitylineNumber>
    <statusCode>Success</statusCode>
    <entityUid>0BA0C06E9CBAA3D890D025A37A577DDB074BA9A9</entityUid>
    <entityMark>1000000115468</entityMark>
  </response>
</ResponseDoc>

我的 xmlReader 变量为空。我还尝试删除 stringReader.ReadLine();但它没有改变任何东西。 我使用它是因为如果编码行存在,它就无法序列化它。

ResponseDoc class :

#region XSD Schema
        [XmlRoot(ElementName = "Responses", Namespace = "")]
        public partial class ResponseDoc
        {

            private ResponseType[] responseField;

            /// <remarks/>
            [System.Xml.Serialization.XmlElement(ElementName = "Response", Namespace = "")]
            public ResponseType[] response
            {
                get
                {
                    return this.responseField;
                }
                set
                {
                    this.responseField = value;
                }
            }
        }

        [XmlRoot(ElementName = "Response", Namespace = "")]
        public partial class ResponseType
        {

            private int entitylineNumberField;

            private string statusCodeField;

            private string uid;

            private string markUid;

            private ResponseTypeErrors[] responseTypeErrors;

            /// <remarks/>
            [XmlElement(ElementName = "inv_number", Namespace = "")]
            public string entitylineNumber
            {
                get
                {
                    return this.entitylineNumberField.ToString();
                }
                set
                {
                    this.entitylineNumberField = int.Parse(value);
                }
            }

            /// <remarks/>
            [XmlElement(ElementName = "StatusCode", Namespace = "")]
            public string statusCode
            {
                get
                {
                    return this.statusCodeField;
                }
                set
                {
                    this.statusCodeField = value;
                }
            }

            [XmlElement(ElementName = "Uid", Namespace = "")]
            public string Uid
            {
                get
                {
                    return this.uid;
                }
                set
                {
                    this.uid = value;
                }
            }

            [XmlElement(ElementName = "Mark", Namespace = "")]
            public string Mark
            {
                get
                {
                    return this.markUid;
                }
                set
                {
                    this.markUid = value;
                }
            }
            [XmlElement(ElementName = "Errors", Namespace = "")]
            public ResponseTypeErrors[] Errors
            {
                get
                {
                    return this.responseTypeErrors;
                }
                set
                {
                    this.responseTypeErrors = value;
                }
            }
        }

        [XmlRoot(ElementName = "Errors", Namespace = "")]
        public partial class ResponseTypeErrors
        {

            private ErrorType[] errorField;

            /// <remarks/>
            [System.Xml.Serialization.XmlElementAttribute("Error")]
            public ErrorType[] error
            {
                get
                {
                    return this.errorField;
                }
                set
                {
                    this.errorField = value;
                }
            }
        }

        [XmlRoot(ElementName = "Error", Namespace = "")]
        public partial class ErrorType
        {

            private string messageField;

            private int codeField;

            /// <remarks/>
            [XmlElement(ElementName = "Message", Namespace = "")]
            public string message
            {
                get
                {
                    return this.messageField;
                }
                set
                {
                    this.messageField = value;
                }
            }

            /// <remarks/>
            [XmlElement(ElementName = "Code", Namespace = "")]
            public int code
            {
                get
                {
                    return this.codeField;
                }
                set
                {
                    this.codeField = value;
                }
            }

        }

        #endregion

更新: 我看到你们所有人都给我关于我的 XSD 模式的答案。 问题不是反序列化 XML。 我的问题是

中的变量 xmlReader
XmlReader xmlReader = XmlReader.Create(stringReader);

是 {None} 尽管我在结果变量中有 xml 答案并将其传递给 stringReader。 我不明白为什么有些人会在我的问题中否定我。我相信很清楚我的问题是什么,我确信我提供了足够的关于我的信息 code.If 我知道更多我会自己解决它。 我还上传了一张带有 strinReader 和 xmlReader 的屏幕截图

每个 属性 的 System.Xml.Serialization.XmlElement 属性中的

ElementName 必须与 XML 中的元素名称相匹配。执行以下操作即可完成修复:

ElementName 对于 ResponseDoc class 应该是 ResponseDoc 而不是 Responses

并且在 ResponseDoc class ElementNameresponse 属性 应该是 response 而不是 响应

ResponseDoc class 应如下所示:

[XmlRoot(ElementName = "ResponseDoc", Namespace = "")]
public partial class ResponseDoc
{

    private ResponseType[] responseField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElement(ElementName = "response", Namespace = "")]
    public ResponseType[] response
    {
        get
        {
            return this.responseField;
        }
        set
        {
            this.responseField = value;
        }
    }
}

并在 ResponseType class 中确保每个 属性 的 ElementName 符合 XML:

ElementName for entitylineNumber 属性 应该是 entitylineNumber 而不是 inv_number

ElementName 对于 statusCode 属性 应该是 statusCode 而不是 StatusCode

其他属性的规则如下:

public partial class ResponseType
    {
        private int entitylineNumberField;

        private string statusCodeField;

        private string uid;

        private long entityMark;

        [XmlElement(ElementName = "entitylineNumber", Namespace = "")]
        public string entitylineNumber
        {
            get
            {
                return this.entitylineNumberField.ToString();
            }
            set
            {
                this.entitylineNumberField = int.Parse(value);
            }
        }

        /// <remarks/>
        [XmlElement(ElementName = "statusCode", Namespace = "")]
        public string statusCode
        {
            get
            {
                return this.statusCodeField;
            }
            set
            {
                this.statusCodeField = value;
            }
        }

        [XmlElement(ElementName = "entityUid", Namespace = "")]
        public string Uid
        {
            get
            {
                return this.uid;
            }
            set
            {
                this.uid = value;
            }
        }


        [XmlElement(ElementName = "entityMark", Namespace = "")]
        public string EntityMark
        {
            get
            {
                return this.entityMark.ToString();
            }
            set
            {
                this.entityMark = long.Parse(value);
            }
        }
    }

如果您可以使用 Nuget 包,我使用我的开源包为您创建了一个解析器 XmlMirror。

安装包XmlMirror.Runtime - 版本 2.2.1

我 post 在这里制作了一个关于我如何制作解析器的视频: https://youtu.be/iGRWDlzVq6s

我将此项目添加为示例项目(希望您不介意我使用您的 Xml 回复 class)。因此,如果您克隆 Xml 镜像,您的示例项目将随它一起安装:

Xml 镜像的完整代码可在此处获得: https://github.com/DataJuggler/XmlMirror

示例代码在这里:

https://github.com/DataJuggler/XmlMirror/tree/master/XmlMirrror/Samples/ResponseLibrary

这是我为解析您的对象而创建的代码(我比我的狗早醒并写得非常快,以向您展示 XmlMirror 是多么简单)。编写这个 post 比构建这个项目花费的时间更长。

Xml 镜像使用反射,所以你必须创建一个 class 库。

我创建了这个 class 叫做 Response.cs:

namespace ResponseLibrary
{

    #region class Response
    /// <summary>
    /// This class is a response from an API call
    /// </summary>
    public class Response
    {

        #region Private Variables
        private int entitylineNumber;
        private string statusCode;
        private string entityUID;
        private string entityMark;
        #endregion

        #region Properties

            #region EntitylineNumber
            /// <summary>
            /// This property gets or sets the value for 'EntitylineNumber'.
            /// </summary>
            public int EntitylineNumber
            {
                get { return entitylineNumber; }
                set { entitylineNumber = value; }
            }
            #endregion

            #region EntityMark
            /// <summary>
            /// This property gets or sets the value for 'EntityMark'.
            /// </summary>
            public string EntityMark
            {
                get { return entityMark; }
                set { entityMark = value; }
            }
            #endregion

            #region EntityUID
            /// <summary>
            /// This property gets or sets the value for 'EntityUID'.
            /// </summary>
            public string EntityUID
            {
                get { return entityUID; }
                set { entityUID = value; }
            }
            #endregion

            #region StatusCode
            /// <summary>
            /// This property gets or sets the value for 'StatusCode'.
            /// </summary>
            public string StatusCode
            {
                get { return statusCode; }
                set { statusCode = value; }
            }
            #endregion

        #endregion

    }
    #endregion

   }

接下来安装nuget包XmlMirror.Runtime

这是使用 Xml 镜像创建的解析器 class:

解析器使用部分classes,所以是一个class,但是两个文件:

ResponsesParser.base.cs

#region using statements

using ResponseLibrary;
using DataJuggler.Core.UltimateHelper;
using System;
using System.Collections.Generic;
using XmlMirror.Runtime.Objects;
using XmlMirror.Runtime.Util;

#endregion

namespace ResponseParserTest.Parsers
{

    #region class ResponsesParser : ParserBaseClass
    /// <summary>
    /// This class is used to parse 'Response' objects.
    /// </summary>
    public partial class ResponsesParser : ParserBaseClass
    {

        #region Methods

            #region ParseResponse(string responseXmlText)
            /// <summary>
            /// This method is used to parse an object of type 'Response'.
            /// </summary>
            /// <param name="responseXmlText">The source xml to be parsed.</param>
            /// <returns>An object of type 'Response'.</returns>
            public Response ParseResponse(string responseXmlText)
            {
                // initial value
                Response response = null;

                // if the sourceXmlText exists
                if (TextHelper.Exists(responseXmlText))
                {
                    // create an instance of the parser
                    XmlParser parser = new XmlParser();

                    // Create the XmlDoc
                    this.XmlDoc = parser.ParseXmlDocument(responseXmlText);

                    // If the XmlDoc exists and has a root node.
                    if ((this.HasXmlDoc) && (this.XmlDoc.HasRootNode))
                    {
                        // Create a new response
                        response = new Response();

                        // Perform preparsing operations
                        bool cancel = Parsing(this.XmlDoc.RootNode, ref response);

                        // if the parsing should not be cancelled
                        if (!cancel)
                        {
                            // Parse the 'Response' object
                            response = ParseResponse(ref response, this.XmlDoc.RootNode);

                            // Perform post parsing operations
                            cancel = Parsed(this.XmlDoc.RootNode, ref response);

                            // if the parsing should be cancelled
                            if (cancel)
                            {
                                // Set the 'response' object to null
                                response = null;
                            }
                        }
                    }
                }

                // return value
                return response;
            }
            #endregion

            #region ParseResponse(ref Response response, XmlNode xmlNode)
            /// <summary>
            /// This method is used to parse Response objects.
            /// </summary>
            public Response ParseResponse(ref Response response, XmlNode xmlNode)
            {
                // if the response object exists and the xmlNode exists
                if ((response != null) && (xmlNode != null))
                {
                    // get the full name of this node
                    string fullName = xmlNode.GetFullName();

                    // Check the name of this node to see if it is mapped to a property
                    switch(fullName)
                    {
                        case "ResponseDoc.response.entitylineNumber":

                            // Set the value for response.EntitylineNumber
                            response.EntitylineNumber = NumericHelper.ParseInteger(xmlNode.FormattedNodeValue, 0, -1);

                            // required
                            break;

                        case "ResponseDoc.response.entityMark":

                            // Set the value for response.EntityMark
                            response.EntityMark = xmlNode.FormattedNodeValue;

                            // required
                            break;

                        case "ResponseDoc.response.entityUid":

                            // Set the value for response.EntityUID
                            response.EntityUID = xmlNode.FormattedNodeValue;

                            // required
                            break;

                        case "ResponseDoc.response.statusCode":

                            // Set the value for response.StatusCode
                            response.StatusCode = xmlNode.FormattedNodeValue;

                            // required
                            break;

                    }

                    // if there are ChildNodes
                    if (xmlNode.HasChildNodes)
                    {
                        // iterate the child nodes
                         foreach(XmlNode childNode in xmlNode.ChildNodes)
                        {
                            // append to this Response
                            response = ParseResponse(ref response, childNode);
                        }
                    }
                }

                // return value
                return response;
            }
            #endregion

        #endregion

    }
    #endregion

}

ResponsesParser.custom.cs

#region using statements

using ResponseLibrary;
using XmlMirror.Runtime.Objects;

#endregion

namespace ResponseParserTest.Parsers
{

    #region class ResponsesParser : ParserBaseClass
    /// <summary>
    /// This class is used to parse 'Response' objects.
    /// </summary>
    public partial class ResponsesParser : ParserBaseClass
    {

        #region Events

            #region Parsing(XmlNode xmlNode)
            /// <summary>
            /// This event is fired BEFORE the collection is initialized.
            /// </summary>
            /// <param name="xmlNode"></param>
            /// <returns>True if cancelled else false if not.</returns>
            public bool Parsing(XmlNode xmlNode)
            {
                // initial value
                bool cancel = false;

                // Add any pre processing code here. Set cancel to true to abort parsing this collection.

                // return value
                return cancel;
            }
            #endregion

            #region Parsing(XmlNode xmlNode, ref Response response)
            /// <summary>
            /// This event is fired when a single object is initialized.
            /// </summary>
            /// <param name="xmlNode"></param>
            /// <param name="response"></param>
            /// <returns>True if cancelled else false if not.</returns>
            public bool Parsing(XmlNode xmlNode, ref Response response)
            {
                // initial value
                bool cancel = false;

                // Add any pre processing code here. Set cancel to true to abort adding this object.

                // return value
                return cancel;
            }
            #endregion

            #region Parsed(XmlNode xmlNode, ref Response response)
            /// <summary>
            /// This event is fired AFTER the response is parsed.
            /// </summary>
            /// <param name="xmlNode"></param>
            /// <param name="response"></param>
            /// <returns>True if cancelled else false if not.</returns>
            public bool Parsed(XmlNode xmlNode, ref Response response)
            {
                // initial value
                bool cancel = false;

                // Add any post processing code here. Set cancel to true to abort adding this object.

                // return value
                return cancel;
            }
            #endregion

        #endregion

    }
    #endregion

}

然后要使用解析器,您所做的就是这样:

(因为我写了一个快速的 Windows 表单来测试它,所以我正在使用按钮点击):

    // xml
    string xml = File.ReadAllText(labelTextBoxBrowserControl1.Text);

    // Create a new instance of a 'ResponsesParser' object.
    ResponsesParser parser = new ResponsesParser();

    // load the response
    Response response = parser.ParseResponse(xml);

    // if the response object exists
    if (response != null)
    {   
        // set each property from the response
        EntityLineNumberControl.Text = response.EntitylineNumber.ToString();
        EntityUIDControl.Text = response.EntityUID;
        StatusCodeControl.Text = response.StatusCode;
        EntityMarkControl.Text = response.EntityMark;
    }

写Xml镜像时,我曾经不得不将Xml解析为我的主要工作之一。

它也解析集合,但我没有为这个例子构建一个集合。