代码之家  ›  专栏  ›  技术社区  ›  dmaruca

XML验证混淆

  •  2
  • dmaruca  · 技术社区  · 16 年前

    我承认,我是个XML新手。我无法根据模式验证某些XML。以下是我的模式的相关部分:

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns="http://www.me.com/orpm/kpi/automation/report"
        targetNamespace="http://www.me.com/orpm/kpi/automation/report">
        <xs:attribute name="Pattern">
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:enumeration value="Exact"/>
                    <xs:enumeration value="Replace"/>
                    <xs:enumeration value="Regex"/>
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
        <xs:complexType name="NameValue">
            <xs:all>
                <xs:element name="Value" type="xs:string"/>
            </xs:all>
            <xs:attribute ref="Pattern"/>
        </xs:complexType>
        <xs:element name="KpiReport">
            <xs:complexType>
                <xs:sequence>
                    <xs:element name="Name" type="NameValue"/>
                </xs:sequence>
            </xs:complexType>
        </xs:element>
    </xs:schema>
    

    以下是失败的XML:

    <?xml version="1.0"?>
    <KpiReport xmlns="http://www.me.com/orpm/kpi/automation/report"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://www.me.com/orpm/kpi/automation/report filename.xsd">
        <Name Pattern="Exact">
            <Value>Test</Value>
        </Name>
    </KpiReport>
    

    失败原因如下:

    Description: cvc-complex-type.2.4.a: Invalid content was found starting with element 'Name'. One of '{Name}' is expected.
    

    我迷路了。请帮忙。

    3 回复  |  直到 16 年前
        1
  •  1
  •   David Hall    16 年前

    有一些事情正在发生,以及一些可能的解决方案。

    您可以使用的解决方案将取决于您是否可以更改XML、XSD或两者。

    下面是一些通过架构验证的XML:

    <?xml version="1.0"?> 
    <ns0:KpiReport xmlns:ns0="http://www.me.com/orpm/kpi/automation/report" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://www.me.com/orpm/kpi/automation/report filename.xsd"> 
        <Name ns0:Pattern="Exact"> 
            <Value>Test</Value> 
        </Name> 
    </ns0:KpiReport>
    

    关键区别在于,在XSD中,您没有在 http://www.me.com/orpm/kpi/automation/report 命名空间。我不完全确定发生了什么,但我认为在模式级别拥有模式属性会混淆事情。通过分配名称空间前缀ns0:来告诉验证器该名称空间中的kpireport和pattern都在,但name不在。

    此解决方案可能不适用,因此另一个选项是调整您的模式以接受示例XML。下面是一个有效的模式:

    <?xml version="1.0" encoding="utf-16"?>
    <xs:schema xmlns:b="http://schemas.microsoft.com/BizTalk/2003" xmlns="http://www.me.com/orpm/kpi/automation/report" targetNamespace="http://www.me.com/orpm/kpi/automation/report" xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:complexType name="NameValue">
        <xs:all>
          <xs:element form="qualified" name="Value" type="xs:string" />
        </xs:all>
        <xs:attribute name="Pattern">
          <xs:simpleType>
            <xs:restriction base="xs:string">
              <xs:enumeration value="Exact" />
              <xs:enumeration value="Replace" />
              <xs:enumeration value="Regex" />
            </xs:restriction>
          </xs:simpleType>
        </xs:attribute>
      </xs:complexType>
      <xs:element name="KpiReport">
        <xs:complexType>
          <xs:sequence>
            <xs:element form="qualified" name="Name" type="NameValue" />
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:schema>
    

    需要注意的是,pattern属性现在被移到name value complexType中,并且该名称和值现在被指定为form=“qualified”。限定意味着这些元素需要名称空间前缀(在本例中,前缀是默认的,或者不需要)。

    我不完全确定为什么需要这样做——我的XSD知识足以达到这一点,但我不太清楚到底发生了什么。我通常使用工具来生成我的模式,然后进行调整,直到我得到正确的结果。

    希望这能帮助您,或者拥有更敏锐XSD技巧的人可以填补空白。

        2
  •  2
  •   dret    16 年前

    david是正确的,但解决这个问题的更好方法是通常将本地定义的元素定义为模式中的限定元素。XSD有一个可怕的默认值(这就是您的XSD不能按预期工作的原因),因此几乎所有工具都会生成一个空模式,如下所示:

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    </xs:schema>
    

    这基本上与david建议的修复相同,但通过更改xsd默认值来实现,后者更为健壮。

    对正在发生的事情的解释可能要花上一点时间才能包括在这里,而且可能没有那么多的兴趣。

        3
  •  2
  •   dret    16 年前

    好的,既然David要求这样做,下面是完整的解释:XSD中的元素声明可以是全局的,也可以是本地的。全局声明位于xs:schema下的级别上,本地声明是其他声明中的声明。定义的全局声明元素始终在架构的targetnamespace中定义(如果有)。另一方面,默认情况下,本地声明不在任何命名空间中(特别是,不在架构的targetnamespace中),除非您通过前面讨论的两个方法之一使它们“限定”。没有名称空间声明的元素的效果是文档必须如下所示(将“name”和“value”元素用作没有名称空间限定名的元素):

    <?xml version="1.0"?> 
    <KpiReport xmlns="http://www.me.com/orpm/kpi/automation/report"> 
        <Name xmlns=""> 
            <Value>Test</Value> 
        </Name> 
    </KpiReport>
    

    这不是很漂亮,很难使用和理解,所以这种混合合格和不合格元素的方式从来没有使用过(我绝对没有见过)。