如何在XSD中引用属性 [英] How to reference an attribute in xsd

查看:146
本文介绍了如何在XSD中引用属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图定义一个可以在后续元素定义中引用的属性.

<xs:attribute name="ridref" type="xs:string"/>

后来我像这样使用它:

<xs:element name="coordRegRef">
  <xs:complexType>
    <!--xs:attribute name="ridref" type="xs:string"/ this works but I want to use ref -->
    <xs:attribute ref="ridref" use="required"/>
  </xs:complexType>
</xs:element>

XSD使用xmllint可以很好地编译

xmllint --schema pc-ar.xsd pc-ar.xml

但是xmllint说

pc-ar.xml:41: element coordRegRef: Schemas validity error : Element '{http://pc-ar.xsd}coordRegRef', attribute 'ridref': The attribute 'ridref' is not allowed.
pc-ar.xml:41: element coordRegRef: Schemas validity error : Element '{http://pc-ar.xsd}coordRegRef': The attribute '{http://pc-ar.xsd}ridref' is required but missing.

我认为这意味着我的XML文件必须为ridref使用命名空间

<coordRegRef fix:ridref="111"/>

(确实有效,但不希望出现),而不是

<coordRegRef ridref="111"/>

为什么?

我的XSD

<?xml version="1.0"?>
<!-- validate: xmllint - -schema pc-ar.xsd pc-ar.xml -->
<xs:schema 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://pc-ar.xsd"
    elementFormDefault="qualified"
    xmlns="http://pc-ar.xsd"
    xmlns:fix="http://pc-ar.xsd">

    <!--xs:attribute name="rid" type="xs:integer"/-->

    <!--xs:attributeGroup name="ridGroup">
    <xs:attribute name="rid" type="xs:integer"> 
        <xs:annotation>
            <xs:documentation>entry id</xs:documentation>
        </xs:annotation>
    </xs:attribute>
</xs:attributeGroup-->

    <xs:element name="name" type="xs:string"/>
    <xs:attribute name="id" type="xs:ID"/>
    <xs:attribute name="idref" type="xs:IDREF"/>

    <xs:attribute name="ridref" type="xs:string"/>

    <xs:element name="coordRegRef">
        <xs:complexType>
            <!--xs:attribute name="ridref" type="xs:string"/works-->
            <xs:attribute ref="ridref" use="required"/>
        </xs:complexType>
    </xs:element>

    <xs:element name="assetRegRef">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="ridref2" type="xs:string"/>
            </xs:sequence>
            <!--xs:attribute name="ridref" type="xs:string"/works-->
            <xs:attribute name="ridref" type="xs:string"/>
        </xs:complexType>
    </xs:element>

    <xs:element name="lat">
        <xs:simpleType>
            <xs:restriction base="xs:decimal">
                <xs:minInclusive value="-40"/>
                <xs:maxInclusive value="-30"/>
            </xs:restriction>
        </xs:simpleType>
    </xs:element>

    <xs:element name="lon" type="xs:decimal"/>

    <xs:complexType name="coordRegTableType">
        <xs:sequence>
            <xs:element name="entry" minOccurs="0" maxOccurs="unbounded">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element ref="name"/>
                        <xs:element ref="lat"/>
                        <xs:element ref="lon"/>
                    </xs:sequence>
                    <xs:attribute name="rid" type="xs:string"/>
                    <!--xs:attribute ref="fix:id" use="required"/-->
                    <xs:attribute name="id" type="xs:string" use="required"/>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="assetRegTableType">
        <xs:sequence>
            <xs:element name="entry" minOccurs="0" maxOccurs="unbounded">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element ref="name"/>
                        <xs:element ref="coordRegRef"/>
                        <xs:element ref="assetRegRef"/>
                    </xs:sequence>
                    <xs:attribute name="rid" type="xs:string"/>
                    <xs:attribute name="id" type="xs:string" use="required"/>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>

    <xs:element name="coordReg" type="fix:coordRegTableType">
        <xs:unique name="coordRegNameUniq">
            <xs:selector xpath="*"/>
            <xs:field xpath="fix:name"/>
        </xs:unique>
    </xs:element>

    <xs:element name="assetReg" type="assetRegTableType">
        <xs:unique name="assetRegNameUniq">
            <xs:selector xpath="fix:entry"/>
            <xs:field xpath="fix:name"/>
        </xs:unique>
    </xs:element>

    <xs:element name="assetExchange">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="coordReg"/>
                <xs:element ref="assetReg"/>
            </xs:sequence>
            <xs:attribute name="rid" type="xs:integer"/>
            <!--xs:attribute ref="id" use="required"/-->
        </xs:complexType>

        <xs:key name="coordRegKey">
            <xs:selector xpath="fix:coordReg/fix:entry"/>
            <xs:field xpath="@rid"/>
        </xs:key>

        <xs:key name="assetRegKey">
            <xs:selector xpath="fix:assetReg/fix:entry"/>
            <xs:field xpath="@rid"/>
        </xs:key>

        <xs:keyref name="assetRegKeyRef" refer="assetRegKey">
            <xs:selector xpath=".//fix:assetRegRef"/>
            <xs:field xpath="@ridref"/>
        </xs:keyref>

        <xs:keyref name="assetRegKeyRef2" refer="assetRegKey">
            <!--xs:selector xpath=".//fix:assetRegRef"/works-->
            <!--xs:selector xpath="./*/*/fix:assetRegRef"/works-->
            <!--xs:selector xpath="./*/fix:entry/fix:assetRegRef"/works-->
            <!--xs:selector xpath="./*/*/fix:assetRegRef"/works-->
            <xs:selector xpath=".//fix:assetRegRef"/> <!-- any assetRefRef -->
            <xs:field xpath="fix:ridref2"/>
        </xs:keyref>

        <xs:keyref name="coordRegKeyRef" refer="coordRegKey">
            <xs:selector xpath=".//fix:coordRegRef"/>
            <xs:field xpath="@ridref"/>
        </xs:keyref>

    </xs:element>

</xs:schema> 

我的XML测试文件

<?xml version="1.0"?>

<assetExchange 
  xmlns="http://pc-ar.xsd"
  xmlns:fix="http://pc-ar.xsd"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://pc-ar.xsd pc-ar.xsd"
  rid="1">

<coordReg>
  <entry id="1" rid="111">
    <name>sitea</name>
    <lat>-31.23</lat>
    <lon>151</lon>
  </entry>

  <entry id="2" rid="222">
    <name>siteb</name>
    <lat>-31.23</lat>
    <lon>151</lon>
  </entry>

  <entry id="3" rid="333">
    <name>sitec</name>
    <lat>-31.23</lat>
    <lon>151</lon>
  </entry>
</coordReg>

<assetReg>
  <entry id="11" rid="11">
    <name>deva</name>
    <coordRegRef fix:ridref="111"/>
    <assetRegRef ridref="aa"><ridref2>aa</ridref2></assetRegRef>
  </entry>

  <entry id="22" rid="22">
    <name>devb</name>
    <coordRegRef ridref="2212"/>
    <assetRegRef ridref="11"><ridref2>11</ridref2></assetRegRef>
  </entry>

  <entry id="33" rid="33">
    <name>devc</name>
    <coordRegRef ridref="333"/>
    <assetRegRef ridref="44"><ridref2>44</ridref2></assetRegRef>
  </entry>

</assetReg>

</assetExchange>

解决方案

正如您所注意到的,从验证错误可以看出,解析器确实希望属性ridref,但它必须位于名称空间中./p>

这样做的原因是,在XML模式中,所有全局元素,属性或类型定义都必须是合格的.这样的结果是,即使您已设置attributeFormDefault="unqualified",所有全局定义的属性都将以名称空间作为前缀.一种解决方法是在<xs:attributeGroup>内部(或在全局类型中)单独定义此类属性.在这种情况下,属性组的名称将附加到其名称空间,而不是其内部的属性名称.然后,您可以使用ref引用这些属性组并获取全局可用的属性,而不必将它们放在命名空间中.

I tried to define an attribute that could be referenced in subsequent element definitions.

<xs:attribute name="ridref" type="xs:string"/>

Later I use it like this:

<xs:element name="coordRegRef">
  <xs:complexType>
    <!--xs:attribute name="ridref" type="xs:string"/ this works but I want to use ref -->
    <xs:attribute ref="ridref" use="required"/>
  </xs:complexType>
</xs:element>

XSD compiles fine with xmllint

xmllint --schema pc-ar.xsd pc-ar.xml

But xmllint says

pc-ar.xml:41: element coordRegRef: Schemas validity error : Element '{http://pc-ar.xsd}coordRegRef', attribute 'ridref': The attribute 'ridref' is not allowed.
pc-ar.xml:41: element coordRegRef: Schemas validity error : Element '{http://pc-ar.xsd}coordRegRef': The attribute '{http://pc-ar.xsd}ridref' is required but missing.

which I interpret as meaning that my XML file must use a namespace for ridref

<coordRegRef fix:ridref="111"/>

(which does work, but undesired) instead of

<coordRegRef ridref="111"/>

Why?

My XSD

<?xml version="1.0"?>
<!-- validate: xmllint - -schema pc-ar.xsd pc-ar.xml -->
<xs:schema 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://pc-ar.xsd"
    elementFormDefault="qualified"
    xmlns="http://pc-ar.xsd"
    xmlns:fix="http://pc-ar.xsd">

    <!--xs:attribute name="rid" type="xs:integer"/-->

    <!--xs:attributeGroup name="ridGroup">
    <xs:attribute name="rid" type="xs:integer"> 
        <xs:annotation>
            <xs:documentation>entry id</xs:documentation>
        </xs:annotation>
    </xs:attribute>
</xs:attributeGroup-->

    <xs:element name="name" type="xs:string"/>
    <xs:attribute name="id" type="xs:ID"/>
    <xs:attribute name="idref" type="xs:IDREF"/>

    <xs:attribute name="ridref" type="xs:string"/>

    <xs:element name="coordRegRef">
        <xs:complexType>
            <!--xs:attribute name="ridref" type="xs:string"/works-->
            <xs:attribute ref="ridref" use="required"/>
        </xs:complexType>
    </xs:element>

    <xs:element name="assetRegRef">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="ridref2" type="xs:string"/>
            </xs:sequence>
            <!--xs:attribute name="ridref" type="xs:string"/works-->
            <xs:attribute name="ridref" type="xs:string"/>
        </xs:complexType>
    </xs:element>

    <xs:element name="lat">
        <xs:simpleType>
            <xs:restriction base="xs:decimal">
                <xs:minInclusive value="-40"/>
                <xs:maxInclusive value="-30"/>
            </xs:restriction>
        </xs:simpleType>
    </xs:element>

    <xs:element name="lon" type="xs:decimal"/>

    <xs:complexType name="coordRegTableType">
        <xs:sequence>
            <xs:element name="entry" minOccurs="0" maxOccurs="unbounded">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element ref="name"/>
                        <xs:element ref="lat"/>
                        <xs:element ref="lon"/>
                    </xs:sequence>
                    <xs:attribute name="rid" type="xs:string"/>
                    <!--xs:attribute ref="fix:id" use="required"/-->
                    <xs:attribute name="id" type="xs:string" use="required"/>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="assetRegTableType">
        <xs:sequence>
            <xs:element name="entry" minOccurs="0" maxOccurs="unbounded">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element ref="name"/>
                        <xs:element ref="coordRegRef"/>
                        <xs:element ref="assetRegRef"/>
                    </xs:sequence>
                    <xs:attribute name="rid" type="xs:string"/>
                    <xs:attribute name="id" type="xs:string" use="required"/>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>

    <xs:element name="coordReg" type="fix:coordRegTableType">
        <xs:unique name="coordRegNameUniq">
            <xs:selector xpath="*"/>
            <xs:field xpath="fix:name"/>
        </xs:unique>
    </xs:element>

    <xs:element name="assetReg" type="assetRegTableType">
        <xs:unique name="assetRegNameUniq">
            <xs:selector xpath="fix:entry"/>
            <xs:field xpath="fix:name"/>
        </xs:unique>
    </xs:element>

    <xs:element name="assetExchange">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="coordReg"/>
                <xs:element ref="assetReg"/>
            </xs:sequence>
            <xs:attribute name="rid" type="xs:integer"/>
            <!--xs:attribute ref="id" use="required"/-->
        </xs:complexType>

        <xs:key name="coordRegKey">
            <xs:selector xpath="fix:coordReg/fix:entry"/>
            <xs:field xpath="@rid"/>
        </xs:key>

        <xs:key name="assetRegKey">
            <xs:selector xpath="fix:assetReg/fix:entry"/>
            <xs:field xpath="@rid"/>
        </xs:key>

        <xs:keyref name="assetRegKeyRef" refer="assetRegKey">
            <xs:selector xpath=".//fix:assetRegRef"/>
            <xs:field xpath="@ridref"/>
        </xs:keyref>

        <xs:keyref name="assetRegKeyRef2" refer="assetRegKey">
            <!--xs:selector xpath=".//fix:assetRegRef"/works-->
            <!--xs:selector xpath="./*/*/fix:assetRegRef"/works-->
            <!--xs:selector xpath="./*/fix:entry/fix:assetRegRef"/works-->
            <!--xs:selector xpath="./*/*/fix:assetRegRef"/works-->
            <xs:selector xpath=".//fix:assetRegRef"/> <!-- any assetRefRef -->
            <xs:field xpath="fix:ridref2"/>
        </xs:keyref>

        <xs:keyref name="coordRegKeyRef" refer="coordRegKey">
            <xs:selector xpath=".//fix:coordRegRef"/>
            <xs:field xpath="@ridref"/>
        </xs:keyref>

    </xs:element>

</xs:schema> 

My XML test file

<?xml version="1.0"?>

<assetExchange 
  xmlns="http://pc-ar.xsd"
  xmlns:fix="http://pc-ar.xsd"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://pc-ar.xsd pc-ar.xsd"
  rid="1">

<coordReg>
  <entry id="1" rid="111">
    <name>sitea</name>
    <lat>-31.23</lat>
    <lon>151</lon>
  </entry>

  <entry id="2" rid="222">
    <name>siteb</name>
    <lat>-31.23</lat>
    <lon>151</lon>
  </entry>

  <entry id="3" rid="333">
    <name>sitec</name>
    <lat>-31.23</lat>
    <lon>151</lon>
  </entry>
</coordReg>

<assetReg>
  <entry id="11" rid="11">
    <name>deva</name>
    <coordRegRef fix:ridref="111"/>
    <assetRegRef ridref="aa"><ridref2>aa</ridref2></assetRegRef>
  </entry>

  <entry id="22" rid="22">
    <name>devb</name>
    <coordRegRef ridref="2212"/>
    <assetRegRef ridref="11"><ridref2>11</ridref2></assetRegRef>
  </entry>

  <entry id="33" rid="33">
    <name>devc</name>
    <coordRegRef ridref="333"/>
    <assetRegRef ridref="44"><ridref2>44</ridref2></assetRegRef>
  </entry>

</assetReg>

</assetExchange>

解决方案

As you noticed, and as it can be seen from the validation error, the parser does expect the attribute ridref but it must be in a namespace.

The reason for that is that in XML Schemas all global element, attribute or type definitions must be qualified. This has the consequence that all your globally defined attributes will be namespace prefixed even if you have set attributeFormDefault="unqualified". A workaround is to define such attributes alone inside <xs:attributeGroup> (or in a global type). In that case the name of the attribute group gets the namespace attached to it instead of the name of the attribute inside it. Then you can use ref to refer to those attribute groups and get your globally usable attributes without having them to be in a namespace.

这篇关于如何在XSD中引用属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆