Xml 参数化允许的数值范围或嵌入类型名称?

Xml 参数化允许的数值范围或嵌入类型名称?,xml,xsd,xsd-1.1,Xml,Xsd,Xsd 1.1,从我所看到的到现在为止,我的问题可能不可能在给定的约束条件下解决,但我会在这里给它一个机会 我正在尝试编写一个XSD(1.1)文件来匹配一个非常简单的XML。问题是XML标记中存在属性,这迫使我使用xs:extension。元素的一个示例: <xs:element name="Index"> <xs:complexType> <xs:simpleContent> <xs:extension base="in

从我所看到的到现在为止,我的问题可能不可能在给定的约束条件下解决,但我会在这里给它一个机会

我正在尝试编写一个XSD(1.1)文件来匹配一个非常简单的XML。问题是XML标记中存在属性,这迫使我使用xs:extension。元素的一个示例:

<xs:element name="Index">
    <xs:complexType>
        <xs:simpleContent>
            <xs:extension base="int1TO10">
                <xs:attribute name="comment" fixed="Attribute in XML Tag"/>
            </xs:extension>
        </xs:simpleContent>
    </xs:complexType>
</xs:element>

而我创建的名为“int1TO10”的类型如下所示:

<xs:simpleType name="int1TO10">
    <xs:restriction base="xs:integer">
        <xs:minInclusive value="1"/>
        <xs:maxInclusive value="10"/>
    </xs:restriction>
</xs:simpleType>

这是可行的,问题是它需要大量的编写,如果您想更改某些内容,则需要更改引用名称以保持与定义类型中的值一致。如果这是一个小文件,这将是可行的;但是这里有相当多的元素,它们可以有几乎任意的最小和最大整数的组合。因此,对于每个新元素,必须有人检查类型是否已经存在,或者必须创建它。这一切都让人觉得难以置信的多余

我要寻找的是一个简单的解决方案,大致如下:

<xs:element>...
    <xs:extension base="xs:integer" minInclusive="1" maxInclusive="10">
        <xs:attribute name="comment" fixed="Attribute in XML Tag"/>
    </xs:extension>...
</xs:element>    
。。。
...
虽然从我的发现来看,这似乎是不可能的。例如,被接受的答案表明,我目前的做法是要走的路;虽然这篇文章已经有点过时了,但也许最近我错过了一些突破

我唯一能想到的另一个选择是从(当前)重新构造XML文件本身

(某些值介于1和10之间)


(某些值介于1和10之间)
属性现在位于其自己的标记中
这还需要做一些工作,并对使用XML的其他一些事情(脚本等)进行更改,所以我宁愿避免这样做


总结一下:有没有一种方法不为我的元素可以拥有的每个新整数组合编写新的simpleType?欢迎您提出任何建议,可能还有一种完全不同的方法或XSD结构?

我认为您所提出的方法是可行的

然而,你可以

  • 对范围类型使用一致的命名方案,如
    int_uu_u_u_u
    ,并使用独立于xml模式的文本处理工具从模板自动生成匹配的xsd类型声明

  • 使用xslt转换您提出的语法(

PoC

生成(perl)

写入包含由系统生成的类型定义组成的xml片段的文件

use IO::File;
use warnings;
use strict;

my ($dict, $fh_out, $fpath, $instance);
my $tmpl =<<EOTMPL;
<xs:simpleType name="int\${lb}TO\${ub}">
    <xs:restriction base="xs:integer">
        <xs:minInclusive value="\${lb}"/>
        <xs:maxInclusive value="\${ub}"/>
    </xs:restriction>
</xs:simpleType>
EOTMPL

my %dict = ( 'lb' => 0,  'ub' => 0 );
$fpath = "<wherever>";
$fh_out = new IO::File ( ">" . $fpath );

for ($dict{lb} = 1; $dict{lb} <= 4; $dict{lb}++ ) {
    for ($dict{ub} = $dict{lb}+1; $dict{ub} <= 4; $dict{ub}++ ) {
        ($instance = $tmpl) =~ s/\$\{([a-z]+)\}/$dict{$1}/g;
        print $fh_out "$instance\n";
    }
}

$fh_out->close;

exit(0);
<?xml-stylesheet version="2.0" encoding="utf-8"?>
<!--
    t.xslt
    XSD typespec generation
-->
<xsl:stylesheet xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <!--
        Specifying the output
    -->
    <xsl:output method="xml" encoding="utf-8" indent="yes"/>

    <!-- identity transform -->
    <xsl:template match="@*|node()">
        <xsl:apply-templates select="@*|node()"/>
    </xsl:template>

    <!--
           Toplevel template:
    -->
    <xsl:template match="/">
        <xsl:message select="string('main template: start;')"/>
        <mytypes xmlns:xs="http://www.w3.org/2001/XMLSchema">
            <xsl:apply-templates />
        </mytypes>
        <xsl:message select="string('main template: end;')"/>
    </xsl:template>

    <!--
           Type subst
    -->
    <xsl:template match="xs:element/xs:complexType/xs:simpleContent/xs:extension[@base='xs:integer'][@minInclusive][@maxInclusive]">
        <xs:simpleType>
            <xsl:attribute name='name' select="concat('int', string(@minInclusive), 'TO', string(@maxInclusive))"/>
            <xs:restriction base="xs:integer">
                <xs:minInclusive><xsl:attribute name='value' select="number(@minInclusive)"/></xs:minInclusive>
                <xs:maxInclusive><xsl:attribute name='value' select="number(@maxInclusive)"/></xs:maxInclusive>
            </xs:restriction>
        </xs:simpleType>
    </xsl:template>
</xsl:stylesheet>
使用IO::File;
使用警告;
严格使用;
我的($dict,$fh_out,$fpath,$instance);
我的$tmpl=0);
$fpath=“”;
$fh_out=新IO::文件(“>”$fpath);
对于($dict{lb}=1;$dict{lb}
基于域的名称 第一个建议:使用对您的域有意义的名称,而不是基于允许范围的名称。例如,使用
Score
而不是
int1TO10
Degrees
而不是
int1TO360
lindenrathanumber
而不是
int323TO9043

除了遵循使用基于域名的最佳实践之外,这种方法还有一个很好的特性,即将范围视为实现细节。如果将来LindenRathan数的最大值从9043更改为9044,那么它可以在定义中更改一次,而不是在名称本身出现的任何地方

完全参数化端点 备选建议:如果出于某些无法解释的原因,在希望公开特定允许范围的位置创建标记很重要,那么您可以一直为端点创建显式XML属性:

<n min="0" max="10">9</n>
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
           vc:minVersion="1.1"> 

  <xs:element name="n" type="IntRangeType"/>

  <xs:complexType name="IntRangeType">
    <xs:simpleContent>
      <xs:extension base="xs:int">
        <xs:attribute name="min" type="xs:int"/>
        <xs:attribute name="max" type="xs:int"/>
        <xs:assert test="@max >= @min"/>
        <xs:assert test=". >= @min and . &lt;= @max"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
</xs:schema>
9
然后,使用XSD 1.1断言,可以将元素值约束在给定端点的范围内:

<n min="0" max="10">9</n>
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
           vc:minVersion="1.1"> 

  <xs:element name="n" type="IntRangeType"/>

  <xs:complexType name="IntRangeType">
    <xs:simpleContent>
      <xs:extension base="xs:int">
        <xs:attribute name="min" type="xs:int"/>
        <xs:attribute name="max" type="xs:int"/>
        <xs:assert test="@max >= @min"/>
        <xs:assert test=". >= @min and . &lt;= @max"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
</xs:schema>


我午餐时也想到了第一个问题,但我希望我能绕开它。我会让它搁置一天左右,如果没有人提出不同的方法,我会接受。我从名称上理解你的观点,但我需要让允许的值在XSD元素的快速视图上可见,所以只使用一个名称,不管怎样很好,只要值不在其中,就不会删除它。将所有的值检查放入断言中肯定是一种可能性,但也会分离元素定义和值范围,因此它将遇到相同的问题。因此,我可能会选择collapsars路线,坚持使用int_x_to_y-Names并创建所有必要的类型谢谢你的标题更新。