如何在嵌套元素标签上使用keyref?

问题描述 投票:0回答:1

我想验证的是。

<root xsi:noNamespaceSchemaLocation="test.xsd" xmlns="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
    <A>
      <a id="ID-1"/>
      <a id="ID-2"/>
    </A>
    <BBB>
      <b>
        <bb>
            <bbb idref="ID-1"></bbb>
        </bb>
      </b>
    </BBB>
</root>

这是我的 .xsd 文件。

  <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" >

  <xsd:element name="root">
    <xsd:complexType>
      <xsd:all minOccurs="1" maxOccurs="1">
        <xsd:element name="A" type="myA"/>
        <xsd:element name="BBB" type="myBBB"/>
      </xsd:all>
    </xsd:complexType>
    <xsd:key name="myId">
      <xsd:selector xpath="./A/a"/>
      <xsd:field xpath="@id"/>
    </xsd:key>

    <xsd:keyref name="myIdref" refer="myId">
      <xsd:selector xpath="./BBB/b/bb/bbb"/>
      <xsd:field xpath="@idref"/>
    </xsd:keyref>
  </xsd:element>

  <xsd:complexType name="myA">
    <xsd:sequence minOccurs="1">
      <xsd:element name="a">
        <xsd:complexType>
          <xsd:attribute name="id" type="xsd:ID"/>
        </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="myBBB">
    <xsd:sequence minOccurs="1">
      <xsd:element name="b">
        <xsd:complexType>
          <xsd:all>
              <xsd:element name="bb">
                  <xsd:complexType>
                      <xsd:sequence>
                          <xsd:element name="bbb">
                              <xsd:complexType>
                                  <xsd:simpleContent>
                                      <xsd:extension base="xsd:string">
                                          <xsd:attribute name="idref" type="xsd:ID"></xsd:attribute>
                                      </xsd:extension>
                                  </xsd:simpleContent>
                              </xsd:complexType>
                          </xsd:element>
                      </xsd:sequence>
                  </xsd:complexType>
              </xsd:element>
          </xsd:all>
        </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>

但是我得到的是:

元素bbb: Schemas有效性错误: 元素'bbb',属性'idref'。 警告: No precomputed value available, the value was either invalid or something strange happend.

我尝试使用 xsd:NCName 但这并没有改变什么。如果我使用 ID-3 还没有定义,我得到的是

没有找到匹配的keyref'myIdref'的key序列['ID-3']。

我想引用的是 id 的A元素与 idref 的bbb元素。我的 xPath 错了吗?我是不是不应该用 xsd:ID 对于 keyRef?

xml xsd xsd-validation
1个回答
1
投票

我猜你的问题是,你想知道 bbb的元素属性类型为 xsd:IDREF 而非 xsd:ID. 那么它将与你的 xsd:ID 定义。

<xsd:attribute name="idref" type="xsd:IDREF"></xsd:attribute>

增加一个小的修正,就是增加一个 maxOccurs="unbounded" 的属性。

...
<xsd:complexType name="myA">
    <xsd:sequence minOccurs="1" maxOccurs="unbounded">
    ...

所以,整个XSD可以是

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" >

  <xsd:element name="root">
    <xsd:complexType>
      <xsd:all minOccurs="1" maxOccurs="1">
        <xsd:element name="A" type="myA"/>
        <xsd:element name="BBB" type="myBBB"/>
      </xsd:all>
    </xsd:complexType>
    <xsd:key name="myId">
      <xsd:selector xpath="./A/a"/>
      <xsd:field xpath="@id"/>
    </xsd:key>

    <xsd:keyref name="myIdref" refer="myId">
      <xsd:selector xpath="./BBB/b/bb/bbb"/>
      <xsd:field xpath="@idref"/>
    </xsd:keyref>
  </xsd:element>

  <xsd:complexType name="myA">
    <xsd:sequence minOccurs="1" maxOccurs="unbounded">
      <xsd:element name="a">
        <xsd:complexType>
          <xsd:attribute name="id" type="xsd:ID"/>
        </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="myBBB">
    <xsd:sequence minOccurs="1">
      <xsd:element name="b">
        <xsd:complexType>
          <xsd:all>
              <xsd:element name="bb">
                  <xsd:complexType>
                      <xsd:sequence>
                          <xsd:element name="bbb">
                              <xsd:complexType>
                                  <xsd:simpleContent>
                                      <xsd:extension base="xsd:string">
                                          <xsd:attribute name="idref" type="xsd:IDREF"></xsd:attribute>
                                      </xsd:extension>
                                  </xsd:simpleContent>
                              </xsd:complexType>
                          </xsd:element>
                      </xsd:sequence>
                  </xsd:complexType>
              </xsd:element>
          </xsd:all>
        </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>

现在你的XSD应该验证你的XML。要做到这一点,你甚至不需要使用

<xsd:key name="myId">
  <xsd:selector xpath="./A/a"/>
  <xsd:field xpath="@id"/>
</xsd:key>

<xsd:keyref name="myIdref" refer="myId">
  <xsd:selector xpath="./BBB/b/bb/bbb"/>
  <xsd:field xpath="@idref"/>
</xsd:keyref>

因为这个功能隐含在 xsd:IDxsd:IDREF 代码。xs:keyref 是更灵活的,但在你的例子中,它是不需要的。


1
投票

你从你的模式处理器中看到了一些非常糟糕的诊断:什么样的软件会输出 "或者一些奇怪的事情发生了 "这样的错误信息?

这是Saxon的输出。

Processing file:/Users/mike/Desktop/temp/test.xml
Validation error on line 4 column 19 of test.xml:
  FORG0001: In content of element <A>: The content model does not allow element <Q{}a> to
  appear more than once. 
  See http://www.w3.org/TR/xmlschema-1/#cvc-complex-type clause 2.4
Validation error on line 4 column 19 of test.xml:
  The field in constraint {myId} has no value
  See http://www.w3.org/TR/xmlschema-1/#cvc-identity-constraint clause 4.2.1
Validation error on line 9 column 27 of test.xml:
  XQDY0027: ID value 'ID-1' is not unique
  See http://www.w3.org/TR/xmlschema-1/#cvc-id clause 2

Let's go through these.

第一个很容易解决,在类型中加入maxOccurs="unbounded"。myA.

当我们修复这个问题后,第二个错误就消失了。我认为Saxon对选择器中XPath表达式的评估 是在假设数据是有效的 而它什么也没找到 因为这个假设并不正确。

第三个错误是由于你在选择器中声明了 bbb/@idref 作为一个xs:ID.如果你把它改成xs:NCName,错误就会消失。如果你把它改成xs:NCName,错误就会消失。

您需要决定是使用 IDIDREF 机制还是使用 keykeyref 机制进行引用完整性检查。两者同时使用是没有意义的。

© www.soinside.com 2019 - 2024. All rights reserved.