首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XSD密钥/密钥引用:分层密钥结构

XSD密钥/密钥引用:分层密钥结构
EN

Stack Overflow用户
提问于 2009-05-21 03:45:15
回答 3查看 8.6K关注 0票数 14

我试图使用xs:key和xs:keyref定义在XML模式上定义一些外键约束。我希望该文件的结构按以下方式分层:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<tns:root xmlns:tns="http://www.example.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/ SampleSchema.xsd ">
  <parent parentKey="parent1">
    <child childKey="child1"/>
    <child childKey="child2"/>
  </parent>
  <parent parentKey="parent2">
    <child childKey="child1"/>
    <child childKey="child2"/>
  </parent>
  <referrer parentRef="parent1" childRef="child2"/>
</tns:root>

A每个父级都有一个(全局的)唯一键,由parentKey定义。每个子节点都有由childKey定义的密钥,但是childKey仅在其包含的父级的范围内是唯一的。

然后有一个具有外键引用的引用特定父和子引用的引用的引用列表。

我可以根据需要定义键,只需将它们放在正确的元素上:根元素上的parentKey约束和父元素上的childKey约束。我也可以毫不费力地将keyref定义为parentKey。

当试图将keyref定义为childKey时会出现问题。我尝试在根元素上为childKey定义一个简单的keyref,但是这不起作用,因为我看不出只选择正确的父子树下的子元素的方法。(至少Eclipse验证器总是简单地针对文档中最后一个父树的内容进行验证.)。

然后,我尝试定义一个复合键(在root上),使用:

  • 选择器=父
  • 字段= @parentKey
  • 字段=child/@child

如果在父级下定义了多个子级,则此操作将失败。这是基于XSD 1.1规范第3.11.4节第3项的正确行为,其中规定每个字段定义的键最多必须匹配一个节点。

重申一下:如果我强制childKeys是全局唯一的,这是很容易实现的;困难在于引用本地唯一的childKeys。

有什么XSD大师有主意吗?

作为参考,下面是一个示例XSD,其中注释掉了一个失败的childKey keyref:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/" xmlns:tns="http://www.example.org/" elementFormDefault="unqualified">

    <element name="root">
        <complexType>
            <sequence>
                <element name="parent" maxOccurs="unbounded" minOccurs="1">
                    <complexType>
                        <sequence>
                            <element name="child" maxOccurs="unbounded" minOccurs="1">
                                <complexType>
                                    <attribute name="childKey" type="string" use="required"/>
                                </complexType>
                            </element>
                        </sequence>
                        <attribute name="parentKey" type="string" use="required"/>
                    </complexType>
                    <key name="childKeyDef">
                        <selector xpath="child"/>
                        <field xpath="@childKey"/>
                    </key>
                </element>
                <element name="referrer" maxOccurs="unbounded" minOccurs="1">
                    <complexType>
                        <attribute name="parentRef" type="string"/>
                        <attribute name="childRef" type="string"/>
                    </complexType>
                </element>
            </sequence>
        </complexType>
        <key name="parentKeyDef">
            <selector xpath="parent"/>
            <field xpath="@parentKey"/>
        </key>
        <keyref name="parentKeyRef" refer="tns:parentKeyDef">
            <selector xpath="referrers"/>
            <field xpath="@parentRef"/>
        </keyref>
<!--        <keyref name="childKeyRef" refer="tns:childKeyDef">-->
<!--            <selector xpath="referrers"/>-->
<!--            <field xpath="@childRef"/>-->
<!--        </keyref>-->
    </element>
</schema>
EN

回答 3

Stack Overflow用户

发布于 2009-05-21 13:47:36

你说孩子的父母怎么样?即使有许多子键,也只会有一个父键,并且组合(父、子)将创建一个全局唯一的键,尽管子键仅在其父键中是唯一的:

代码语言:javascript
复制
  <key name="childKeyDef">
    <selector xpath="child"/>
    <field xpath="@childKey"/>
    <field xpath="../@parentKey"/>
  </key>

这在xmllint中不起作用,尽管规范似乎没有显式地不允许在字段中这样做--仅用于选择器:3.11.4,(2)表示选择器不能是祖先(只能是上下文节点或后代)。

啊,这是棺材的钉子(看看具体的语法):允许的XPath表达式非常有限,只是不包括“.”http://www.w3.org/TR/xmlschema-1/#c-fields-xpaths

所以,对不起,这没有回答你的问题,但也许它会给你一些想法。

票数 3
EN

Stack Overflow用户

发布于 2009-05-22 08:38:12

一个丑陋的解决方案是更改XML格式,以便在每个子程序中都包含parentKey,如下所示:

代码语言:javascript
复制
<parent>
  <child parentKey="parent1" childKey="child1"/>
  <child parentKey="parent1" childKey="child2"/>
</parent>

我认为您的情况是非常合理的,我希望有一种方法来做到这一点--为什么不试试xml-dev邮件列表呢?据我所知,它变得很嘈杂,但是xml的一些创建者仍然在那里徘徊。

票数 1
EN

Stack Overflow用户

发布于 2009-09-01 15:53:38

我有一个类似的问题:具有多个字段的XML键

我决定,对我来说最好的方法是重新排序XML,以便允许由本地来确定范围,而不是用两个字段强制执行密钥。

在您的场景中,如果您在父级中移动引用器,这将允许将范围设置为引用适当的子元素。然后,您将让referrer元素将外部范围引用到它需要引用的元素。

要确定这是否是一个可接受的解决方案有点困难,因为您的问题似乎有点抽象。在我的问题中,在我的问题中,我处理的是问题、答案和用户的回答。我最初试图验证用户的响应是否实际上是一个有效的答案;我的第一种方法涉及您正在使用的相同的技术。我的最后一个解决方案是将响应移到问题的内部,然后引用用户。

我以前的XML:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<survey>
  <user id="bob">
    <response questionIdRef="q101">yes</response>
    <response questionIdRef="q102">white</response>
  </user>
  <user id="jane">
    <response questionIdRef="q101">no</response>
    <response questionIdRef="q102">blue</response>
  </user>
  <question id="q101">
    <text>Do you like the color red?</text>
    <answer>yes</answer>
    <answer>no</answer>
  </question>
  <question id="q102">
    <text>What is your favorite color?</text>
    <answer>red</answer>
    <answer>blue</answer>
    <answer>white</answer>
    <answer>yellow</answer>
  </question>
</survey>

我的XML之后:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<survey>
  <user id="bob" />
  <user id="jane" />
  <question id="q101">
    <text>Do you like the color red?</text>
    <answer>yes</answer>
    <answer>no</answer>
    <response userIdRef="bob">yes</response>
    <response userIdRef="jane">no</response>
  </question>
  <question id="q102">
    <text>What is your favorite color?</text>
    <answer>red</answer>
    <answer>blue</answer>
    <answer>white</answer>
    <answer>yellow</answer>
    <response userIdRef="bob">white</response>
    <response userIdRef="jane">blue</response>
  </question>
</survey>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/891324

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档