【问题标题】:How to make an XML tag mandatory with a self-closing tag, using the serialiser?如何使用序列化程序使 XML 标记强制使用自闭合标记?
【发布时间】:2022-01-21 21:01:25
【问题描述】:

我正在开发一个 C# 程序,我正在尝试序列化 XML。

我有以下标签:

using System.Xml.Serialization;
...
[XmlElement("MV")]
public MultiVerse MultiVerse { get; set; }

当我不填写这个值时,标签<MV>不存在,但我想在这种情况下获得标签<MV/>

目前我有<HM><ID>Some_ID</ID></HM>
我想要<HM><ID>Some_ID</ID><MV/></HM>

我已经尝试在前面加上[Required],但这没有用,我认为填写IsNullable 属性是个好方法。

Edit1,经过网上调查
网上有不少关于修改XmlWriter的建议,但在我的项目中,整个序列化是这样完成的:

public override string ToString()
{
    ...
    using (var stream = new StringWriter())
    using (var writer = XmlWriter.Create(stream, settings))
    {
        var serializer = new XmlSerializer(base.GetType());
        serializer.Serialize(writer, this, ns);
        return stream.ToString();
    }
    ...
}

如您所见,这太笼统了,我不想在这里做任何修改,因此我正在寻找一种方法来自定义 [XmlElement] 指令。

Edit2:XmlWriter 设置:
XmlWriter settings 如下所示:

// Remove Declaration
var settings = new XmlWriterSettings
{
    Indent = false,
    OmitXmlDeclaration = true,
    NewLineHandling = NewLineHandling.None,
    NewLineOnAttributes = false,
};

有人有想法吗?

提前致谢

【问题讨论】:

  • MultiVerse 类的外观如何?
  • MultiVerse 类是另一个类,具有一些属性,其中一些还具有[XmlElement()] 指令,但整个类可以是null,而后者是我的情况有兴趣。
  • 其实我有一大堆类,互相引用。 XML 序列化器把它变成了一堆嵌套的 XML,这是正确的。经常发生其中一个对象是null,然后这在生成的 XML 中不可见,这很好。但是,对于那个类,MultiVerse 类,我希望看到一个条目,它可以采用自闭合标签的形式。

标签: c# xml serialization xml-serialization


【解决方案1】:

这是我目前解决问题的方式(别笑):

public override string ToString()
{
    string temp = base.ToString();
    temp = temp.Replace(" p2:nil=\"true\"", "");
    temp = temp.Replace(" xmlns:p2=\"http://www.w3.org/2001/XMLSchema-instance\"", "");
    temp = temp.Replace("MV />", "MV/>");
    return temp;
}

这太可怕了!有人有更好的解决方案吗?

谢谢

【讨论】:

    【解决方案2】:

    https://docs.microsoft.com/en-us/dotnet/api/system.xml.serialization.xmlelementattribute.isnullable?view=net-6.0 所以例如

    [XmlElement("MV", IsNullable=true)]
    public MultiVerse MultiVerse { get; set; }
    

    对于空值,会给你一个序列化为<MV xsi:nil="true" />(或者可能是<MV xsi:nil="true"></MV>,以确保短标签符号不是标准编写者让你控制的东西,但我的经验是.NET通常使用它对于空元素,因此您可能很幸运,您想要的序列化格式是默认的 .NET 输出)。

    【讨论】:

    • 我可以确认它确实存在,但它看起来像<HM><ID>546791133</ID><TC>MS</TC><MV p2:nil="true" xmlns:p2="http://www.w3.org/2001/XMLSchema-instance" /></HM>,而我想要<HM><ID>546791133</ID><TC>MS</TC><MV/></HM>(我要发送它的机器,非常挑剔),这可能吗?
    • 内置的 XSD nil <--> C# null 映射确实以这种方式表示它,因此我可以根据序列化程序 API 中的现有功能和自定义属性提出建议。对于其他任何我认为您需要深入研究 API 或对结果进行后处理的事情,我不记得您是否或如何调整更多设置,或者后处理是否是唯一的方法。
    • 我添加了XmlWriter 设置,因为我在我的应用程序中找到了它们,但我认为它们不是导致这种奇怪的序列化结果的原因。尽管如此,也许有一些XmlWriter 设置可以删除那些过时的条目。任何想法? (也许是NamespaceHandling?)
    • 我不认为在使用XmlSerializer 的基于XSD 的序列化的定义上下文中,使用xsi:type 没有任何奇怪或过时的地方,它只是用于区分例如一个空的<foo/> 代表public String Foo { get; set; } 代表来自<foo xsi:nil="true"/> 的空字符串值,代表一个空的Foo 值。至于没有xsi:nil,正如我所说,我不确定是否有办法,Serialize 方法采用 XmlSerializerNamespaces 对象,但它似乎没有提供抑制/删除命名空间绑定的方法,例如xsi 命名空间。
    • 所以总结如下:IsNullable 属性提供了显示标签的可能性,但它的呈现方式远非良好,因为存在命名空间相关信息。因此,或者,应该有一种方法可以删除所有这些信息,或者应该存在另一种方法来将此特定标签添加为自封闭,以防null
    猜你喜欢
    • 2011-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多