如何正确表示空的XML元素?

181

我看到过几种表示null元素的方式:

元素存在但值为null,并使用 xsi:nil="true" 表示:


元素存在,但值为 null,并使用 xsi:nil="true" 表示:
 <book>
     <title>Beowulf</title>
     <author xsi:nil="true"/>
 </book>

该元素存在,但被表示为空元素(我认为这是错误的,因为“空”和null在语义上是不同的):

 <book>
     <title>Beowulf</title>
     <author/>
 </book>

 <!-- or: -->
 <book>
     <title>Beowulf</title>
     <author></author>
 </book>

在返回的标记中根本不存在该元素:

 <book>
     <title>Beowulf</title>
 </book>

该元素有一个<null/>子元素(来自下面的TStamper):

 <book>
     <title>Beowulf</title>
     <author><null/></author>
 </book>

有没有一种正确或规范的方式来表示这样一个null值?除了以上示例外,还有其他方法吗?

上面的示例XML是人为构造的,所以不要读得太深入。 :)

7个回答

132

xsi:nil是一种正确的表示值的方式,以便: 当发出DOM Level 2调用getElementValue()时,将返回NULL值。 即使该元素的内容类型通常不允许空元素,xsi:nil也用于指示没有内容的有效元素。

如果使用空标记,则getElementValue()返回空字符串("") 如果省略标记,则根本没有作者标记存在。这可能在语义上不同于将其设置为“nil”(例如,将“系列”设置为nil可能意味着该书不属于任何系列,而省略系列可以意味着系列不适用于当前元素。)

来自:W3C

  

XML Schema: Structures引入了一种机制,用于在具有不要求或甚至不允许为空内容的内容类型的情况下接受元素,同时信号传递该元素应被视为·valid·。 如果它具有属性xsi:nil且值为true,则可在没有内容的情况下使元素·valid·。 标记为如此的元素必须为空,但如果相应的复杂类型允许,则可以携带属性。

澄清:
如果您有一个book的xml元素,并且其中一个子元素是book:series,则在填写它时有几个选项:

  1. 完全删除元素-当您希望指示该系列不适用于此书或该书不属于系列时,可以执行此操作。 在这种情况下,具有匹配book:series的模板的xsl转换(或其他基于事件的处理器)永远不会被调用。 例如,如果您的xsl将book元素转换为表行(xhtml:tr),则使用此方法可能会得到错误的表单元格(xhtml:td)数量。
  2. 留空元素 - 这可能表示系列是“”,或者是未知的,或者该书不属于系列。任何匹配book:series的xsl转换(或其他基于事件的解析器)都将被调用。current()的值将为“”。使用此方法将获得与下一个描述的方法相同数量的xhtml:td标记。
  3. 使用xsi:nil="true" - 这表示book:series元素为NULL,而不仅仅是空的。你的xsl转换(或其他基于事件的解析器)将被调用,以匹配book:series的模板。current()的值为空(而不是空字符串)。这种方法与(2)之间的主要区别在于,book:series的模式类型不需要允许空字符串("")作为有效值。这在系列元素中没有实际意义,但对于在模式中定义为枚举类型的语言元素来说,xsi:nil="true"允许元素没有数据。另一个例子是decimal类型的元素。如果您希望它们为空,可以联合只允许""和十进制数的枚举字符串,或使用可为空的十进制数。

11
使用xsi:nil是正确的,但你需要确保它在正确的命名空间中:xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"。 - STW
实际上是 xmlns:xsi="http://w3.org/2001/XMLSchema-instance"。请注意缺少的 http://。这很重要,因为命名空间字符串实际上只是一个字符串,而不是 URI,对于 XML 解析器来说。 - Burak Arslan
11
嘿,我相信还是有点错。应该是 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"。注意要有 "www."。请参见 http://www.w3.org/TR/xmlschema-1/#no-xsi。 - Janne Mattila
正如我在回答中所述,我不同意这种解释,因为它并不代表元素的状态,而是对元素使用的限制。 - Oakcool
根据www.w3.org/TR/xmlschema-1的规定,xsi:nil属性声明是内置的,因此不需要(甚至可能不允许)声明xsi命名空间。 - ChrisV
2
@ChrisV:不是这样的,必须声明xsi:前缀。如果您尝试在未声明的情况下使用xsi:前缀,一个命名空间感知的XML解析器将拒绝您的XML文档。相关规范在此处http://www.w3.org/TR/xml-names/#nsc-NSDeclared(“命名空间约束:前缀已声明”),其中指出唯一的预定义前缀是`xml:`和`xmlns:`。XML Schema建立在XML命名空间规范之上,但没有向其添加任何其他预定义前缀,因为这样做实际上会违反XML命名空间规范。 - Simon Kissane

13

没有通用的答案,因为XML基本上没有“null”概念。但我假设你想要Xml/Object映射(因为对象图有nulls); 所以对于你来说,答案是“无论你的工具使用什么”。如果您编写处理程序,则意味着使用任何您喜欢的内容。对于使用XML Schema的工具,xsi:nil是正确的方式。对于大多数映射器,省略匹配的元素/属性是正确的方法。


9

在w3的链接中,文件说明如下:

http://www.w3.org/TR/REC-xml/#sec-starttags

推荐使用以下这些形式:

<test></test>
<test/>

在另一个答案中提到的属性是一种验证机制,而不是状态表示。请参考:http://www.w3.org/TR/xmlschema-1/#xsi_nil XML Schema: Structures引入了一种机制,用于在元素没有内容的情况下发出“有效”信号,尽管内容类型不要求甚至不一定允许空内容。如果一个元素具有值为true的xsi:nil属性,则可以在没有内容的情况下是“有效”的。所标记的元素必须为空,但如果相应的复杂类型允许,则可以携带属性。
为了澄清这个答案:
<?xml version="1.0" encoding="utf-8" ?>
<Books>
  <Book>
    <!--This element should alway be empty-->
    <BuildAttributes HardCover="true" Glued="true" xsi:nil="true"/>
    <Index></Index>
    <pages>
      <page pageNumber="1">Content</page>
    </pages>
    <!--Valid representation of a null or empty ISBN-->
    <ISBN></ISBN>
  </Book>

  <Book>
    <!--Invalid construct since the element attribute xsi:nil="true" signal that the element must be empty-->
    <BuildAttributes HardCover="true" Glued="true" xsi:nil="true">
      <anotherAttribute name="Color">Blue</anotherAttribute>
    </BuildAttributes>
    <Index></Index>
    <pages>
      <page pageNumber="1">Content</page>            
    </pages>
    <!--Missing ISBN could be confusing and misguiding since its not present-->
  </Book>
</Books>

9
这是关于空元素的建议;您认为空 === null 吗?我相信两者之间有区别,尽管这通常取决于情况。如果您认为它们是相同的,我建议在您的答案中提及该论点。 - Rob Hruska
1
空不等于null;如果是这样的话,这个stackoverflow问题就永远不会被提出了。这个答案是错误的。然而,程序员应该确定将读取xml的逻辑是否准备好处理缺少的元素或xsi:nil;如果没有,可能需要使用其中一种形式;也就是说,可能需要失去null/缺少元素和空元素之间的区别。 - ToolmakerSteve
@RobHruska 是的,你说得对,这是一个空元素的定义,但是如果考虑到KitsuneYMG指出的W3C定义,它定义了该元素必须为空,我认为这种表示更多地是标签的定义,而不是其当前状态的表示,因此我不同意那个答案,并且认为空元素是表示空元素的最佳方式。 这个想法很简单,为了保持良好的结构,你需要所有元素都被表示,否则你就不会知道它的存在,从而可能误代它。 - Oakcool

9

这取决于您如何验证XML。如果您使用XML Schema验证,正确表示null值的方式是使用xsi:nil属性。

[来源]


4
当您的模式语义表明元素具有默认值,并且如果该元素不存在,则应使用默认值时,您可以使用xsi:nil。我必须假设有些聪明的人认为前面的句子并不是一个显然糟糕的想法,但对我来说听起来像九种糟糕的想法。我曾经使用过的每种XML格式都通过省略元素(或属性)来表示空值。(而且希望使用xsi:nil标记属性好运。)

如果在文档发布应用程序中,您希望标题页上的日期默认为当前日期(如果元素没有内容),那么完全省略date元素并不是很有帮助,因为应用程序将不知道您希望日期出现在标题页的哪个位置。(如果省略的元素只有一个可能的位置,则这不是问题;但在实际文档词汇表中,几乎所有元素都有许多可能的位置。) - C. M. Sperberg-McQueen

4

在不太正式的数据中,简单地省略属性或元素即可。

如果您需要更复杂的信息,GML模式还添加了nilReason属性,例如:GeoSciML:

  • 使用值为“true”的xsi:nil表示无可用值
  • 可以使用nilReason记录有关缺失值的其他信息;这可以是标准GML原因之一(missing, inapplicable, withheld, unknown),也可以是以other:开头的文本,或者可以是指向更详细说明的URI链接。

当您交换数据时,XML常用于的角色,发送给一个接收者或用于特定目的的数据可能会隐藏内容,而该内容对于支付或具有不同身份验证的其他人将可用。知道为什么内容丢失非常重要。

科学家们也关心信息丢失的原因。例如,如果由于质量原因而删除了信息,则他们可能希望查看原始坏数据。


2
在许多情况下,Null值的目的是为了代表应用程序先前版本中不存在的数据值。
假设您有一个来自您的应用程序“ReportMaster”版本1的XML文件。
现在,在ReportMaster版本2中,可能已添加了一些更多的属性,这些属性可能已定义或未定义。
如果您使用“无标记表示为空”表示法,则可以自动实现向后兼容性,以读取您的ReportMaster 1 XML文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接