使用XSD验证具有空命名空间的嵌套XML元素

时间:2013-09-01 20:41:43

标签: xml xsd

我正在尝试验证一堆看似大致相似的XML文件(示例full file在Gist中):

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- ... -->
  <ProjectExtensions>
    <Borland.Personality>Default.Personality</Borland.Personality>
    <Borland.ProjectType />
    <BorlandProject>
  <BorlandProject xmlns=""> <Default.Personality> </Default.Personality> </BorlandProject></BorlandProject>
  </ProjectExtensions>
  <!-- ... -->
</Project>

我知道嵌套的<BorlandProject xmlns="">很奇怪,但我们存储库中的很多XML文件都是这样的,我想验证它们。

文件使用MSBuild定义的子集。到目前为止,我已尝试过这样的事情(再次:在{Gist上full file):

<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" version="1.0"
  targetNamespace="http://schemas.microsoft.com/developer/msbuild/2003"
  xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="Project" type="ProjectType"/>
  <!-- ... -->
  <xsd:complexType name="ProjectExtensionsType">
    <xsd:sequence>
      <xsd:element name="Borland.Personality" type="xsd:string"/>
      <xsd:element name="Borland.ProjectType" type="xsd:string"/>
      <xsd:element name="BorlandProject" type="BorlandProjectType"/>
    </xsd:sequence>
  </xsd:complexType>
  <xsd:complexType name="BorlandProjectType">
    <xsd:choice>
      <xsd:sequence>
        <xsd:element name="Default.Personality" type="xsd:string"/>
      </xsd:sequence>
      <xsd:element name="BorlandProject" type="BorlandProjectType"/>
    </xsd:choice>
  </xsd:complexType>
  <!-- ... -->
</xsd:schema>

使用如下错误消息验证barfs:

Error: The element 'BorlandProject' in namespace 'http://schemas.microsoft.com/developer/msbuild/2003'  
has invalid child element 'BorlandProject'.  
List of possible elements expected:   
'Default.Personality, BorlandProject' in namespace 'http://schemas.microsoft.com/developer/msbuild/2003'.  
<BorlandProject>

我认为这是因为xmlns=""内的奇怪<BorlandProject xmlns="">

两个问题:

  1. 我的xmlns=""假设是对的吗?
  2. 如何验证此<BorlandProject xmlns="">元素?
  3. 修改

    感谢 ColdFusion 的回答。这是我最终做的,因为BorlandProject可以是合格的和不合格的:

      <xsd:complexType name="BorlandProjectType">
        <xsd:choice>
          <xsd:sequence>
            <xsd:element name="Default.Personality" type="xsd:string"/>
          </xsd:sequence>
          <!-- Delphi <= 2010 can have a nested `BorlandProject` element, sometimes unqualified (with xmlns=""), sometimes qualified -->
          <xsd:choice>
            <xsd:element name="BorlandProject" form="unqualified" type="BorlandProjectTypeUnqualified"/>
            <xsd:element name="BorlandProject" type="BorlandProjectTypeQualified"/>
          </xsd:choice>
        </xsd:choice>
      </xsd:complexType>
      <xsd:complexType name="BorlandProjectTypeUnqualified">
        <xsd:sequence>
          <xsd:element name="Default.Personality" form="unqualified" type="xsd:string"/>
        </xsd:sequence>
      </xsd:complexType>
      <xsd:complexType name="BorlandProjectTypeQualified">
        <xsd:sequence>
          <xsd:element name="Default.Personality" type="xsd:string"/>
        </xsd:sequence>
      </xsd:complexType>
    

2 个答案:

答案 0 :(得分:3)

  

我的xmlns =“”假设是对吗?

是。 xmlns=""没有错。 “”也是命名空间 - 全局命名空间(或“非空格”)。

  

如何验证此元素?

nonamespace中的元素称为不合格

只要您需要不合格的所有元素都是本地元素(嵌套在其他元素中),就可以使用form="unqualified"属性专门声明(对于每个特定元素)。

注意:是否使用elementFormDefault属性指定所有本地元素(在架构中定义)是否合格 在<xsd:schema>。但你可以把它混合起来,以便让一些本地元素合格,而不是一些。

例如,您的XML文件(在您的问题中提供)可以根据此模式进行验证:

<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
  version="1.0"
  targetNamespace="http://schemas.microsoft.com/developer/msbuild/2003"
  xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">

  <xsd:element name="Project" type="ProjectType"/>

  <xsd:complexType name="ProjectType">
    <xsd:sequence>
      <xsd:element name="ProjectExtensions" type="ProjectExtensionsType"/>
    </xsd:sequence>
  </xsd:complexType>

  <!-- ... -->
  <xsd:complexType name="ProjectExtensionsType">
    <xsd:sequence>
      <xsd:element name="Borland.Personality" type="xsd:string"/>
      <xsd:element name="Borland.ProjectType" type="xsd:string"/>
      <xsd:element name="BorlandProject" type="BorlandProjectType"/>
    </xsd:sequence>
  </xsd:complexType>
  <xsd:complexType name="BorlandProjectType">
    <xsd:choice>
      <xsd:sequence>
        <xsd:element name="Default.Personality" type="xsd:string"
                     form="unqualified"/>
      </xsd:sequence>
      <xsd:element name="BorlandProject" type="BorlandProjectType"
                   form="unqualified"/>
    </xsd:choice>
  </xsd:complexType>
  <!-- ... -->
</xsd:schema>

请注意,根据该架构,您实际上有两个BorlandProject元素:一个在http://schemas.microsoft.com/developer/msbuild/2003中,另一个在没有命名空间中。我不知道,你是否真的需要这个...但这就是你的XML编写方式。

答案 1 :(得分:1)

  1. 是的,删除xmlns =“”后,XML验证。

  2. a)最简单的解决方案是从XML中删除无效的xmlns。

    b)更难的是你导入的另一个模式没有名称空间,可以定义另一个可以引用的BorlantProjectType。我试过这个并且无法让它发挥作用。

    c)另一种可能性是基于XML生成新模式,然后对其进行验证。我做了那个,然后调整了一下,在包含发生中得到了嵌套。然而,由于这只是针对一个样本进行测试,因此可能需要进行一些调整。 XSD在这里https://gist.github.com/anonymous/6408209&amp; https://gist.github.com/Dijkgraaf/6408223

  3. 编辑:    d)回答ColdFusion给出的答案,这更简单。