如预期LinqToXml不处理的nillable元素(LinqToXml does not hand

2019-07-04 07:36发布

根据W3C标准,如果你有一个零值的nillable元素,你应该像这样格式化:

<myNillableElement xsi:nil="true" />

但是,如果你使用这个LinqToXml声明...

element.Add(
    new XElement(ns + "myNillableElement", null);

...生成的XML是...

<myNillableElement />

......这是无效的。 而根据微软自己的XML / XSD验证根据W3C不仅无效,无效的。 所以,下一次您验证XML,你会得到错误。

我失去了一些开关,可以打开的nillable元素的正确处理?

谢谢。

Answer 1:

LINQ到XML是大都没有模式感知 - 它可以让你验证树,但它并没有得到来自任何特定的语义。 你的错误是认为null应该以某种方式始终映射到xsi:nil 。 有没有在W3C规范没有这样的要求(而很明显,因为它们不包括任何种类的语言绑定)。

尤其XElement你实际调用构造函数采用类型的参数object[]这是孩子们的名单-没有理由传球null到应该有任何相关性xsi:nil 。 在任何情况下,如何LINQ到XML应该知道你生成XML,根据一些模式是有效的,并且在此架构一个特定元素nilled="true"



Answer 2:

你也可以做这样的事情,走的是空合并运算符的优势:

public static object Nil
{
    get
    {
        // **I took a guess at the syntax here - you should double check.**
        return new XAttribute(Xsi + "nil", true);
    }
}

// ......

object nullableContent = ...;
element.Add(
    new XElement(NS + "myNillableElement", nullableContent ?? Nil)
    );


Answer 3:

但愿,这不是理想的答案,但我写了一对夫妇的扩展方法,至少使其更容易一些,以应对LinqToXml的nillable元素。

扩展方法:

public static class XElementExtensions
{
    private static XName _nillableAttributeName = "{http://www.w3.org/2001/XMLSchema-instance}nil";

    public static void SetNillableElementValue(this XElement parentElement, XName elementName, object value)
    {
        parentElement.SetElementValue(elementName, value);
        parentElement.Element(elementName).MakeNillable();
    }

    public static XElement MakeNillable(this XElement element)
    {
        var hasNillableAttribute = element.Attribute(_nillableAttributeName) != null;
        if (string.IsNullOrEmpty(element.Value))
        {
            if (!hasNillableAttribute)
                element.Add(new XAttribute(_nillableAttributeName, true));
        }
        else
        {
            if (hasNillableAttribute)
                element.Attribute(_nillableAttributeName).Remove();
        }
        return element;
    }
}

用法示例

// "nil" attribute will be added
element.Add(
    new XElement(NS + "myNillableElement", null)
    .MakeNillable();

// no attribute will be added
element.Add(
    new XElement(NS + "myNillableElement", "non-null string")
    .MakeNillable();

// "nil" attribute will be added (if not already present)
element.SetNillableElementValue(NS + "myNillableElement", null);

// no attribute will be added (and will be removed if necessary)
element.SetNillableElementValue(NS + "myNillableElement", "non-null string");


文章来源: LinqToXml does not handle nillable elements as expected