【问题标题】:How to prevent adding XML element if XElement is Null? [duplicate]如果 XElement 为 Null,如何防止添加 XML 元素? [复制]
【发布时间】:2013-02-04 16:25:47
【问题描述】:

我有一个简单的 XML 文档,如下所示:

<Person>
  <LastName>LastName1</LastName>
  <FirstName>FirstName1</FirstName>
  <MiddleName>MiddleName1</MiddleName>
  <Suffix>Suffix1</Suffix>
</Person>

但是我有一个限制,我 不允许 添加空标签。因此,如果Suffix 值不存在,我将无法使用&lt;Suffix /&gt;,否则验证将失败。

我正在使用来自不同类的XElement 对象组成XML 结构,这些对象通过.ToXML() 方法返回的XElement 对象返回各自的XML。我需要检查 每个元素 以查看返回的 XElement 是否为 null。如果是这样的话,它必须就像那条线从未存在过。我正在尝试使用 ?? 运算符,但出现 ??左操作数永远不会为空。我的代码如下:

public XElement ToXML()
{
  return new XElement("Employee",
    new XElement(this.LastName.ToXML()) ?? null,
    new XElement(this.FirstName.ToXML()) ?? null,
    new XElement(this.MiddleName.ToXML()) ?? null,
    new XElement(this.Suffix.ToXML()) ?? null);
}

如何检查每个 XML 节点以查看返回的 XElement 对象是否为空,如果是,则忽略一起添加/组合该节点?任何帮助表示赞赏,谢谢!

【问题讨论】:

  • ToXML() 方法的返回类型是什么?如果是XElement,为什么要围绕它创建一个新的XElement
  • 不,你是对的,当方法已经返回 XElement 实例时,我不应该使用 new。我不应该把它放在示例中,但我会把它留给未来的读者。

标签: c# xml linq-to-xml xelement


【解决方案1】:

您应该改用此代码:

public XElement ToXML()
{
    var children = new[]
    {
        this.LastName.ToXML(),
        this.FirstName.ToXML(),
        this.MiddleName.ToXML(),
        this.Suffix.ToXML()
    };

    return new XElement("Employee", children.Where(x => x != null));
}

请注意,您的代码有几个问题:

  1. null 合并运算符 (??) 是当左侧值为 null 时返回右侧值的运算符。制作右手值null 完全没用。
  2. new 语句与?? 混合使用运算符也完全没用,因为new 的结果永远不会是null
  3. new XElement 部分似乎也没什么用。我假设ToXML 已经返回了XElement,那么为什么要创建一个新实例呢?

【讨论】:

  • 正确的#3,确实没用,因为方法已经返回了元素。
【解决方案2】:

C# 中的构造函数将返回对对象的非空引用或抛出异常。它不会返回 null*。

至于你的问题,何乐而不为:

return new XElement("Employee",
    this.LastName.ToXML(),
    this.FirstName.ToXML(),
    this.MiddleName.ToXML(),
    this.Suffix.ToXML());

如果不存在ToXML 方法中的每一个都返回null

或者如果您的情况是属性本身为空:

return new XElement("Employee",
    this.LastName != null ? this.LastName.ToXML() : null, /* null is ignored */
    this.FirstName != null ? this.FirstName.ToXML() : null,
    this.MiddleName != null ? this.MiddleName.ToXML() : null,
    this.Suffix != null ? this.Suffix.ToXML() : null);

我也刚刚意识到,也许你总是会返回一个XElement,但它可能是,在这种情况下:

var elements = new[] { this.LastName.ToXML(), this.FirstName.ToXML(), ...

// use IsEmpty to filter out those that are <Element/>
return new XElement("Employee",
    elements.Where(ee => ee != null && !ee.IsEmpty));

*我相信有一个有趣的边缘案例,您可以从 COM 接口实例化中得到它,但我们将忽略所有“奇怪”的编码。

【讨论】:

  • 如果我使用您的第一种方法并返回null,那么您说它不会自动将节点添加到XElement 根,对吗? Mening 我不必像我想的那样在你的第二个样本中明确检查?
  • @atconway: 这是正确的,如果他们返回 null 那很好。显然它不能作为节点添加,因为它不知道要添加的节点、属性等。
  • 如果您的第三个示例中显示的elements 中元素的顺序保留,那么我认为这似乎也是一个不错的解决方案。
  • @atconway:是的,它们被保留了。
  • @atconway:是的,如果他们总是返回它,第三种方法很有用。我将空检查包含在“未来”证明中,以防止在 Where 子句中引发异常。
猜你喜欢
  • 1970-01-01
  • 2012-01-07
  • 2020-12-06
  • 1970-01-01
  • 2021-05-07
  • 1970-01-01
  • 2011-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多