【问题标题】:Unique attributes with xpath not workingxpath 的独特属性不起作用
【发布时间】:2013-05-08 20:42:29
【问题描述】:

我想使用 xsd 模式文件验证 xml 文档。 xml 文档包含有关 windows 服务的信息,我想将 Service 中的 Name 属性设置为唯一值。

这是一个小的 xml 示例:

<?xml version="1.0" encoding="utf-8"?>
<Services xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://example.de/xml/services">
  <Service Name="ALG" StartMode="Manual" State="Stopped">
    <DisplayName>xyz</DisplayName>
  </Service>
  <Service Name="AllUserInstallAgent" StartMode="Manual" State="Stopped">
    <DisplayName>xyz</DisplayName>
  </Service>
  <Service Name="AllUserInstallAgent" StartMode="Manual" State="Stopped">
    <DisplayName>xyz</DisplayName>
  </Service>
    <Service Name="AllUserInstallAgent" StartMode="Manual" State="Stopped">
    <DisplayName>xyz</DisplayName>
  </Service>
</Services>

我尝试使用 xpath 进行以下操作:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://example.de/xml/services" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://example.de/xml/services">
  <xsd:element name="Services">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element maxOccurs="unbounded" name="Service">
          <xsd:complexType>
            <xsd:sequence>
              <xsd:element name="DisplayName" type="xsd:string" />
            </xsd:sequence>
            <xsd:attribute name="Name" type="xsd:string" use="required" />
            <xsd:attribute name="StartMode" type="xsd:string" use="required" />
            <xsd:attribute name="State" type="xsd:string" use="required" />
          </xsd:complexType>
          <xs:unique name="Unique-Name">
            <xs:selector xpath="Service" />
            <xs:field xpath="@Name" />
          </xs:unique>
        </xsd:element>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xs:schema>

但遗憾的是 xml 文档仍然有效。请注意,有些记录具有相同的Name

我做错了什么?我发现了这个how to make an attribute unique in xml schema?XML XSD Schema - Enforce Unique Attribute Values in Schema。这里有什么不同?

【问题讨论】:

    标签: xml validation xsd unique


    【解决方案1】:

    这是关于范围和命名空间的。

    如果您可视化您的结构,并记住选择器植根于与约束相关联的元素中......

    您可能会注意到您正在寻找“服务...”下的“服务”,但该服务不存在。因此,第一步是将其移动到适当的元素(服务)下。

    上述仍然不起作用的原因与您使用命名空间的事实有关,并且元素是合格的。这意味着您必须为目标命名空间添加一个 XML 命名空间前缀(此处为 tns)。所以这是您更正后的 XSD:

    <?xml version="1.0" encoding="utf-8" ?>
    <!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
    <xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://example.de/xml/services" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://example.de/xml/services" xmlns:tns="http://example.de/xml/services">
        <xsd:element name="Services">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element maxOccurs="unbounded" name="Service">
                        <xsd:complexType>
                            <xsd:sequence>
                                <xsd:element name="DisplayName" type="xsd:string"/>
                            </xsd:sequence>
                            <xsd:attribute name="Name" type="xsd:string" use="required"/>
                            <xsd:attribute name="StartMode" type="xsd:string" use="required"/>
                            <xsd:attribute name="State" type="xsd:string" use="required"/>
                        </xsd:complexType>
                    </xsd:element>
                </xsd:sequence>
            </xsd:complexType>
            <xs:unique name="Unique-Name">
                <xs:selector xpath="tns:Service"/>
                <xs:field xpath="@Name"/>
            </xs:unique>
        </xsd:element>
    </xs:schema>
    

    这将适当地标记您的 XML:

    Error occurred while loading [], line 11 position 5
    There is a duplicate key sequence 'AllUserInstallAgent' for the 'http://example.de/xml/services:Unique-Name' key or unique identity constraint.
    Error occurred while loading [], line 14 position 5
    There is a duplicate key sequence 'AllUserInstallAgent' for the 'http://example.de/xml/services:Unique-Name' key or unique identity constraint.
    

    【讨论】:

    • 谢谢,我明天马上测试!你用的是哪个工具?我看到有 xmlns、xmlns:tns 和 targetNamespace 具有相同的值,有必要吗?我也试过没有命名空间,我删除了targetNamespace,但也没有用,为什么?度过美好的一天。
    • @hofmeister,targetNamespace 必须符合您的要求;您不需要定义具有相同值的默认命名空间;但是,许多人认为这是一种最佳做法; tns 是任意的,您仍然需要为您的 targetNamespace 定义一个别名并使用它,因为元素是合格的,如果没有前缀,则选择器/字段中的 XPath 假定没有命名空间,而不是默认命名空间;该工具是QTAssistant,这是我们开发的。
    • 但是如果我将约束移动到服务下并设置默认命名空间 xmlns,为什么它仍然不起作用?我不明白为什么我需要 xmls、xmls:prefix 和 targetnamespace.. 如果你能解释一下就好了!
    • @hofmeister,正如我已经说过的,这是因为默认命名空间不适用于用于选择器和字段的 XPath;因此,如果您需要从命名空间中识别元素/属性,则需要为其定义别名。如果规范中的这种“不对称”让您感到困扰(即为什么它需要一个前缀而不是默认值),那么请考虑在同一 XPath 中使用混合(限定/非限定名称)的场景。拥有默认的 xmlns eq targetNamespace 只是最佳实践;你不需要它,但它肯定更容易,否则你还必须......
    • (续)限定 XSD 中的所有其他引用名称。例如而不是 您将需要 等。如果您想深入了解,那么您必须继续阅读XSD 如何使用 NCName 和 QName,以及 XML 命名空间的一般工作方式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多