根据W3C标准,如果你有一个零值的nillable元素,你应该像这样格式化:
<myNillableElement xsi:nil="true" />
但是,如果你使用这个LinqToXml声明...
element.Add(
new XElement(ns + "myNillableElement", null);
...生成的XML是...
<myNillableElement />
......这是无效的。 而根据微软自己的XML / XSD验证根据W3C不仅无效,无效的。 所以,下一次您验证XML,你会得到错误。
我失去了一些开关,可以打开的nillable元素的正确处理?
谢谢。
LINQ到XML是大都没有模式感知 - 它可以让你验证树,但它并没有得到来自任何特定的语义。 你的错误是认为null
应该以某种方式始终映射到xsi:nil
。 有没有在W3C规范没有这样的要求(而很明显,因为它们不包括任何种类的语言绑定)。
尤其XElement
你实际调用构造函数采用类型的参数object[]
这是孩子们的名单-没有理由传球null
到应该有任何相关性xsi:nil
。 在任何情况下,如何LINQ到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");