XmlSerializer.Serialize 剥离 标记

本文关键字:标记 xml Serialize 剥离 XmlSerializer | 更新日期: 2023-09-27 18:31:46

我正在尝试与支付处理器进行通信。当我使用XmlSerializer.Serialize 在我的对象上,我得到

<?xml version='"1.0'" encoding='"utf-16'"?>
<txn xmlns:xsi='"http://www.w3.org/2001/XMLSchema-instance'" xmlns:xsd='"http://www.w3.org/2001/XMLSchema'">
  <ssl_merchant_id>xxxxxx</ssl_merchant_id>
  <ssl_user_id>xxxxxx</ssl_user_id>
  <ssl_pin>xxxxxx</ssl_pin>
  <ssl_test_mode>True</ssl_test_mode>
  <ssl_transaction_type>ccavsonly</ssl_transaction_type>
  <ssl_card_number>4111111111111111</ssl_card_number>
  <ssl_exp_date>0612</ssl_exp_date>
  <ssl_avs_address>101 Main St.</ssl_avs_address>
  <ssl_avs_zip>90210</ssl_avs_zip>
</txn>

在使用该方法之前,我手动构建了用于测试的 XML,这有效:

<txn>
  <ssl_merchant_id>xxxxxx</ssl_merchant_id>
  <ssl_user_id>xxxxxx</ssl_user_id>
  <ssl_pin>xxxxxx</ssl_pin>
  <ssl_test_mode>True</ssl_test_mode>
  <ssl_transaction_type>ccavsonly</ssl_transaction_type>
  <ssl_card_number>4111111111111111</ssl_card_number>
  <ssl_exp_date>0612</ssl_exp_date>
  <ssl_avs_address>101 Main St.</ssl_avs_address>
  <ssl_avs_zip>90210</ssl_avs_zip>
</txn>

我将如何从 XML 中删除<?xml version='"1.0'" encoding='"utf-16'"?>xmlns:xsi='"http://www.w3.org/2001/XMLSchema-instance'" xmlns:xsd='"http://www.w3.org/2001/XMLSchema'">,或者一开始就不让序列化程序生成它?

我的对象如下所示:

[XmlRoot(ElementName="txn")]
public class AvsTransmission
{
    [XmlElement]
    public string ssl_merchant_id { get; set; }
    [XmlElement]
    public string ssl_user_id { get; set; }
    [XmlElement]
    public string ssl_pin { get; set; }
    [XmlElement]
    public string ssl_test_mode { get; set; }
    [XmlElement]
    public string ssl_transaction_type { get; set; }
    [XmlElement]
    public string ssl_card_number { get; set; }
    [XmlElement]
    public string ssl_exp_date { get; set; }
    [XmlElement]
    public string ssl_avs_address { get; set; }
    [XmlElement]
    public string ssl_avs_zip { get; set; }
}

XmlSerializer.Serialize 剥离 <xml> 标记

我的第一个答案只是问题的一半,您还必须删除已经提到的声明。

下面是一个示例:

XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
MemoryStream ms = new MemoryStream();
XmlWriter writer = XmlWriter.Create(ms, settings);
XmlSerializerNamespaces names = new XmlSerializerNamespaces();
names.Add("", "");
XmlSerializer cs = new XmlSerializer(typeof(Cat));
cs.Serialize(writer, new Cat { Lives = 9 }, names);
ms.Flush();
ms.Seek(0, SeekOrigin.Begin);
StreamReader sr = new StreamReader(ms);
var xml = sr.ReadToEnd();

字符串xml现在包含:

<cat><Lives>9</Lives></cat>

第一个函数将对象转换为xml字符串,第二个函数同时转换对象并将xml写入文件。

    public static string Serialize<T>(T obj)
    {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.OmitXmlDeclaration = true;
        var writer = new StringWriter();
        XmlWriter xmlWriter = XmlWriter.Create(writer, settings);
        XmlSerializerNamespaces names = new XmlSerializerNamespaces();
        names.Add("", "");
        XmlSerializer serializer = new XmlSerializer(typeof(T));
        serializer.Serialize(xmlWriter, obj, names);
        var xml = writer.ToString();
        return xml;
    }
    public static void Serialize<T>(T obj, string filepath)
    {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.OmitXmlDeclaration = true;
        var writer = new StreamWriter(filepath);
        XmlWriter xmlWriter = XmlWriter.Create(writer, settings);
        XmlSerializerNamespaces names = new XmlSerializerNamespaces();
        names.Add("", "");
        XmlSerializer serializer = new XmlSerializer(typeof(T));
        serializer.Serialize(xmlWriter, obj, names);
    }

实际上,我意识到代码重复自己。在这些方法中,只更改一个东西,即编写器对象,因此代码必须如下所示。通过这种方式,只需更改编写器对象类型即可轻松使用代码。

    public static string Serialize<T>(T obj)
    {
        var writer = new StringWriter();
        Serialize<T>(obj,writer);
        var xml = writer.ToString();
        return xml;
    }
    public static void Serialize<T>(T obj, string filepath)
    {
        var writer = new StreamWriter(filepath);
        Serialize<T>(obj,writer);
    }
    public static void Serialize<T>(T obj, TextWriter writer)
    {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.OmitXmlDeclaration = true;
        XmlWriter xmlWriter = XmlWriter.Create(writer, settings);            
        XmlSerializerNamespaces names = new XmlSerializerNamespaces();
        names.Add("", "");            
        XmlSerializer serializer = new XmlSerializer(typeof(T));            
        serializer.Serialize(xmlWriter, obj, names);
    }

与@payo的原始答案非常相似:

如果要删除命名空间,您可能还想删除版本,为了节省搜索时间,我添加了该功能,因此下面的代码将同时执行这两项操作。

我还将其包装在一个通用方法中,因为我正在创建非常大的 xml 文件,这些文件太大而无法在内存中序列化,所以我将输出文件分解并以较小的"块"对其进行序列化:

public string XmlSerialize<T>(T entity) where T : class
{
    // removes version
    XmlWriterSettings settings = new XmlWriterSettings();
    settings.OmitXmlDeclaration = true;
    XmlSerializer xsSubmit = new XmlSerializer(typeof(T));
    StringWriter sw = new StringWriter();
    using (XmlWriter writer = XmlWriter.Create(sw, settings))
    {
        // removes namespace
        var xmlns = new XmlSerializerNamespaces();
        xmlns.Add(string.Empty, string.Empty);
        xsSubmit.Serialize(writer, entity, xmlns);
        return sw.ToString(); // Your XML
    }
}

如果使用 XmlWriter,则有一个设置可以省略声明http://msdn.microsoft.com/en-us/library/system.xml.xmlwritersettings.omitxmldeclaration.aspx

我将举一个例子,但这可能足以让你开始。


编辑:下面是在 LinqPad 中运行的示例

string test  = "test";
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
MemoryStream strm = new MemoryStream();
XmlWriter writer = XmlWriter.Create(strm, settings);
XmlSerializer serializer =  new XmlSerializer(typeof(string));
serializer.Serialize(writer, test);
strm.Position = 0;
StreamReader reader = new StreamReader(strm);
var x = reader.ReadToEnd();
x.Dump();
writer.Close();
reader.Close();
strm.Close();

输出

<string>test</string>

注释掉第 3 行,输出为

<?xml version="1.0" encoding="utf-8"?><string>test</string>

只是为了简化删除 UTF 编码声明的原始问题的解决这是代码

                StringBuilder sb = new StringBuilder();
                var serializer = new System.Xml.Serialization.XmlSerializer(typeToSerialize.GetType());
                serializer.Serialize(System.Xml.XmlWriter.Create(sb, new System.Xml.XmlWriterSettings { OmitXmlDeclaration = true, Indent=true }), typeToSerialize);