【问题标题】:Unable to extend XML complex types with the parent type in a namespace无法使用命名空间中的父类型扩展 XML 复杂类型
【发布时间】:2016-08-23 11:59:08
【问题描述】:

我在尝试从 XSD 扩展复杂类型时遇到问题。症结在于——我试图实现的复杂类型在一个命名空间中,并且这个相同的命名空间被设置为父级的targetNamespace

这里是父 XSD(相关部分)

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:tns="http://schemas.mandiant.com/2010/ioc" 
           elementFormDefault="qualified" 
           targetNamespace="http://schemas.mandiant.com/2010/ioc" 
           xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="ioc" nillable="true" 
              type="tns:IndicatorOfCompromise" />
  <xs:complexType name="IndicatorOfCompromise">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="1" 
                  name="short_description" type="xs:string" />
      <xs:element minOccurs="0" maxOccurs="1" 
                  name="description" type="xs:string" />
      <xs:element minOccurs="0" maxOccurs="1" 
                  name="keywords" type="xs:string" />
      <xs:element minOccurs="0" maxOccurs="1" 
                  name="authored_by" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" 
                  name="authored_date" nillable="true" 
                  type="xs:dateTime" />
      <xs:element minOccurs="0" maxOccurs="1" 
                  name="links" type="tns:ArrayOfLink" />
      <xs:element minOccurs="0" maxOccurs="1" 
                  name="definition" type="tns:ArrayOfIocIndicator" />
    </xs:sequence>
    <xs:attribute name="id" type="xs:string" />
    <xs:attribute name="last-modified" type="xs:dateTime" 
                  use="required" />
  </xs:complexType>
</xs:schema>

这就是我尝试扩展的方式(基本上是添加更多元素)

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           targetNamespace="http://schemas.mandiant.com/2010/ioc" >
    <xs:import namespace="urn:tns" 
               schemaLocation="openioc_schema_v10.xsd" />
    <xs:redefine schemaLocation="openioc_schema_v10.xsd">
      <xs:complexType name="IndicatorOfCompromise">
        <xs:complexContent>
          <xs:extension base="tns:IndicatorOfCompromise">
            <xs:sequence>
                <xs:element name="category" type="xs:string" />
                <xs:element name="family" type="xs:string" />
            </xs:sequence>
          </xs:extension>
        </xs:complexContent>
      </xs:complexType>
    </xs:redefine>
</xs:schema>

当我尝试针对此架构验证以下 XML 时,

<?xml version='1.0' encoding='UTF-8'?>
<ioc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
     xmlns="http://schemas.mandiant.com/2010/ioc" 
     id="2555192b-186b-441d-bbdd-1d2fb41f462f" 
     last-modified="2016-05-12T12:14:50"
     xmlns:qioc_v10="ioc_qualys_v10.xsd" 
     xsi:schemaLocation="ioc_qualys_v10.xsd">
  <short_description>Bagsu!rfn</short_description>
  <description>This is a placeholder for description of the Bagsu!rfn malware family.</description>
  <keywords/>
  <authored_by>IOC_api</authored_by>
  <authored_date>2016-05-12T12:14:50</authored_date>
  <qioc_v10:category>XYZ</qioc_v10:category>
  <qioc_v10:family>XYZ 2</qioc_v10:family>
  <links/>
</ioc>

它给出错误“元素信息项的命名空间属性'urn:tns'必须与导入文档的目标名称空间属性'http://schemas.mandiant.com/2010/ioc'相同。”

该怎么做呢?我已经阅读了几篇关于此的 Stackoverflow 帖子,但似乎没有一个可以解决我的难题。我已经理解我需要扩展的元素驻留在命名空间中但不知道如何修复它的问题。

请注意,我不能以任何方式触摸父 xsd。这是OpenIOC 标准。

【问题讨论】:

    标签: xml xsd schema


    【解决方案1】:

    您可能想阅读有关 XSD 导入、包含、重新定义和(对于 XSD 1.1)覆盖的基础知识。这将减少你必须做的猜测。

    在这种情况下,您的本地修改有几个问题,所有这些问题都与您必须猜测要做什么而不是清楚地了解模式文档间引用的含义有关。

    1. 首先,导入语句与您建议导入的架构文档不兼容。您显示的本地架构具有:

      <xs:import namespace="urn:tns" 
             schemaLocation="openioc_schema_v10.xsd" />
      

      这意味着“这里声明的组件可以引用命名空间 urn:tns 的架构组件;该命名空间的架构文档可以在 openioc_schema_v10.xsd 找到。”但如果模式处理器接受您的提示并尝试读取 openioc_schema_v10.xsd,它会发现其目标命名空间是 http://schemas.mandiant.com/2010/ioc,而不是 urn:tns。它不可能为命名空间 urn:tns 声明任何组件,因此不能在命名空间 urn:tns 的导入的 schemaLocation 属性中有用地命名它。

    2. 当然,您可以通过在 import 语句中指定正确的命名空间来解决此问题:

      <xs:import namespace="http://schemas.mandiant.com/2010/ioc" 
             schemaLocation="openioc_schema_v10.xsd" />
      

      如果您这样做,您将收到一条新的不同的错误消息,因为您正在尝试为您的目标命名空间导入架构。正如普通英语中的“import”意味着将外国商品引入国内市场一样,XSD 中的“import”意味着从其他(外部)命名空间引入模式组件。您不能为目标命名空间导入架构。这就是 xsd:include 的用途。

    3. 如果您将导入更改为包含,您可能会或可能不会获得引发错误消息的架构,但您不会获得跨实现可靠工作的架构,因为现在您都包含(未更改的)版本openioc_schema_v10.xsd(通过包含)并包括它的修改版本(通过重新定义)。

      最好完全消除 import-which-should-be-an-include 。在 openioc_schema_v10.xsd 中定义的架构的重新定义将引入该架构的所有架构组件,以及您的重新定义所指定的修改。

    4. 如果您删除错误和不必要的导入,您会发现您的 IndicatorOfCompromise 类型声明指定了 tns:IndicatorOfCompromise 的基本类型,但是现在您的架构文档中的任何地方都没有将命名空间前缀 tns 绑定到任何命名空间。你想要

      xmlns:tns="http://schemas.mandiant.com/2010/ioc"
      

    在 xs:extension 元素或祖先上。

    这些是第一眼就能看到的机械问题;可能还有更多。正如我所说:找到一个好的教程,阅读它,学习包含、导入、重新定义和覆盖的基础知识。

    另一件事:如果您要扩展一个公开定义的类型,那么您可能应该在自己的命名空间中定义新类型,而不是通过重新定义某人拥有的命名空间中的类型别的。但这会让我们走得太远。祝你好运。

    【讨论】:

      猜你喜欢
      • 2017-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多