有没有办法在序列化XML时删除* only * xmlns:xsd命名空间?

时间:2018-01-23 01:39:59

标签: c# xml xml-serialization xmlserializer

我使用xsd2code ++创建了一个序列化对象。它工作正常,除了以下内容:

出于某种原因,我需要发送的XML需要有一些名称空间,但不是xsd名称(即使,据我所知,列出它应该没有问题,但那不是我的呼叫)。我在生成的c#类中有以下代码:

[XmlNamespaceDeclarations]
public XmlSerializerNamespaces xmlns;

[XmlAttribute("schemaLocation", Namespace = XmlSchema.InstanceNamespace)]
public string xsiSchemaLocation = "http://www.sat.gob.mx/TimbreFiscalDigital http://www.sat.gob.mx/sitio_internet/cfd/TimbreFiscalDigital/TimbreFiscalDigitalv11.xsd";
public TimbreFiscalDigital()
{
  this.versionField = "1.1";
  this.xmlns = new XmlSerializerNamespaces();
  this.xmlns.Add("tfd", "http://www.sat.gob.mx/TimbreFiscalDigital");
  this.xmlns.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
}

在类本身的属性中,我有以下内容:

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.sat.gob.mx/TimbreFiscalDigital")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.sat.gob.mx/TimbreFiscalDigital", IsNullable = false)]

但XML包含xmlns:xsd="http://www.w3.org/2001/XMLSchema"名称空间声明。

我在这里看到了关于如何完全删除用于序列化的命名空间的不同答案,但它并不是我想要的,我只是希望我设置的那些是唯一的那些序列化的。

任何方法都可以删除xsd,而无需使用自定义xml序列化程序或类似的东西?我觉得可能有一些我可以设置的属性或选项(或者我设置不正确)会影响这一点,但我在对象的代码中看不到对xsd的任何引用。我已经通过XmlSerializer.Serialize()直接调用了序列化程序。

1 个答案:

答案 0 :(得分:2)

XmlNamespaceDeclarationsAttribute

解释了root不影响根元素的名称空间前缀的原因,尽管不清楚。
  

另请注意,应用该属性的成员仅包含属于类的XML元素的前缀 - 命名空间对。例如,在以下XML文档中,只有前缀对&#34; cal&#34;被捕获,但不是&#34; x&#34;字首。要获取该数据,请将具有XmlNamespaceDeclarationsAttribute的成员添加到表示<?xml version="1.0"?> <x:root xmlns:x="http://www.cohowinery.com/x/"> <x:select xmlns:cal="http://www.cohowinery.com/calendar/" path="cal:appointments/@cal:startTime" /> </x:root> 元素的类中。

XmlNamespaceDeclarationsAttribute

这意味着返回的prefix-namespace对将被添加到当前元素的属性中,并在序列化子元素(那些属于当前元素)时使用 - 但是不影响当前元素本身的名称空间前缀。要做到这一点,必须将XmlSerializer成员添加到 - 但当然,根元素没有父元素。

如果没有控制根元素的名称空间前缀的属性,则必须使用其documentation重载之一手动调用Serialize()。如果您使用的XmlSerializerNamespaces重载不包含XmlNamespaceDeclarations,例如XmlSerializer.Serialize(Writer, Object, XmlSerializerNamespaces),那么序列化程序将始终帮助向根元素添加一组默认命名空间,包括:

  • 根元素本身所需的命名空间;
  • 标准&#34; xsd&#34;和&#34; xsi&#34;命名空间;
  • 子节点所需的其他命名空间;
  • public static partial class XmlSerializationHelper { public static string GetXml<T>(this T obj, XmlSerializer serializer = null, XmlSerializerNamespaces ns = null) { ns = ns ?? obj.GetXmlNamespaceDeclarations(); using (var textWriter = new StringWriter()) { var settings = new XmlWriterSettings() { Indent = true }; // For cosmetic purposes. using (var xmlWriter = XmlWriter.Create(textWriter, settings)) (serializer ?? new XmlSerializer(obj.GetType())).Serialize(xmlWriter, obj, ns); return textWriter.ToString(); } } public static XmlSerializerNamespaces GetXmlNamespaceDeclarations<T>(this T obj) { if (obj == null) return null; var type = obj.GetType(); return type.GetFields() .Where(f => Attribute.IsDefined(f, typeof(XmlNamespaceDeclarationsAttribute))) .Select(f => f.GetValue(obj)) .Concat(type.GetProperties() .Where(p => Attribute.IsDefined(p, typeof(XmlNamespaceDeclarationsAttribute))) .Select(p => p.GetValue(obj, null))) .OfType<XmlSerializerNamespaces>() .SingleOrDefault(); } public static XmlSerializerNamespaces With(this XmlSerializerNamespaces xmlns, string prefix, string ns) { if (xmlns == null) throw new ArgumentNullException(); xmlns.Add(prefix, ns); return xmlns; } } 成员返回的其他命名空间。

这是你所看到的行为。

因此,以下扩展方法将根据需要序列化根对象:

var root = new TimbreFiscalDigital();
var xml = root.GetXml();

然后,如果您按如下方式序列化您的类型:

<tfd:TimbreFiscalDigital xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sat.gob.mx/TimbreFiscalDigital http://www.sat.gob.mx/sitio_internet/cfd/TimbreFiscalDigital/TimbreFiscalDigitalv11.xsd" xmlns:tfd="http://www.sat.gob.mx/TimbreFiscalDigital">
  <tfd:version>1.1</tfd:version>
</tfd:TimbreFiscalDigital>

生成以下XML:

TimbreFiscalDigital.xmlns

示例XmlSerializer.Serialize(XmlWriter, Object)

顺便提一下,如果[XmlNamespaceDeclarations]返回的命名空间是固定的,并且您不需要在反序列化期间捕获它们,则可以使用已应用[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.sat.gob.mx/TimbreFiscalDigital")] [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.sat.gob.mx/TimbreFiscalDigital", IsNullable = false)] public class TimbreFiscalDigital { string versionField; //[XmlAttribute] public string version { get { return versionField; } set { versionField = value; } } [XmlNamespaceDeclarations] public XmlSerializerNamespaces Xmlns { get { return new XmlSerializerNamespaces() .With("tfd", "http://www.sat.gob.mx/TimbreFiscalDigital") .With("xsi", XmlSchema.InstanceNamespace); } set { /* Do nothing */ } } [XmlAttribute("schemaLocation", Namespace = XmlSchema.InstanceNamespace)] public string xsiSchemaLocation = "http://www.sat.gob.mx/TimbreFiscalDigital http://www.sat.gob.mx/sitio_internet/cfd/TimbreFiscalDigital/TimbreFiscalDigitalv11.xsd"; public TimbreFiscalDigital() { this.versionField = "1.1"; } } 的属性替换该字段,如此:

XmlSerializerNamespaces

该属性必须同时具有getter和setter,但是当getter始终返回//load soundcloud js api if needed var script = document.createElement('script'); script.type = 'text/javascript'; script.src = 'http://w.soundcloud.com/player/api.js'; document.head.appendChild(script); //get the id of the player iframe or inject it using chrome var id = 'scplayer', widgetIframe = document.getElementById(id), fixWidget = SC.Widget(widgetIframe); fixWidget.setVolume(50); //% between 1 and 100 的新实例时,setter无法执行任何操作。通过这样做,您可以减少班级的永久性内存占用。

示例fiddle