LinqToXml不按预期处理可为空的元素

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

 

但是如果你使用这个LinqToXml语句……

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

……生成的XML是……

  

……这是无效的。 根据W3C,不仅无效,根据微软自己的XML / XSDvalidation器无效。 因此,下次validationXML时,会出现错误。

我错过了一些可以打开正确处理可支付元素的开关吗?

谢谢。

LINQ to XML主要不是模式感知的 – 它允许您validation树,但它不会从中派生任何特定的语义。 你的错误是相信null应该以某种方式总是映射到xsi:nil 。 W3C规范中没有这样的要求(很明显,因为它们不包括任何类型的语言绑定)。

特别是,您调用的XElement构造函数实际上采用了object[]类型的参数,这是一个子列表 – 没有理由将null传递给它应该与xsi:nil有任何关联。 在任何情况下,LINQ to XML如何知道您根据某些模式生成有效的XML,并且此模式中的一个特定元素是否为nilled="true"

你也可以做这样的事情,利用空合并运算符:

 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) ); 

希望这不是理想的答案,但我写了几个扩展方法,至少使它更容易处理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");