Xml 参数化允许的数值范围或嵌入类型名称?
从我所看到的到现在为止,我的问题可能不可能在给定的约束条件下解决,但我会在这里给它一个机会 我正在尝试编写一个XSD(1.1)文件来匹配一个非常简单的XML。问题是XML标记中存在属性,这迫使我使用xs:extension。元素的一个示例: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
<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结构?我认为您所提出的方法是可行的 然而,你可以
- 对范围类型使用一致的命名方案,如
,并使用独立于xml模式的文本处理工具从模板自动生成匹配的xsd类型声明int_uu_u_u_u
- 使用xslt转换您提出的语法(
)
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 . <= @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 . <= @max"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>
我午餐时也想到了第一个问题,但我希望我能绕开它。我会让它搁置一天左右,如果没有人提出不同的方法,我会接受。我从名称上理解你的观点,但我需要让允许的值在XSD元素的快速视图上可见,所以只使用一个名称,不管怎样很好,只要值不在其中,就不会删除它。将所有的值检查放入断言中肯定是一种可能性,但也会分离元素定义和值范围,因此它将遇到相同的问题。因此,我可能会选择collapsars路线,坚持使用int_x_to_y-Names并创建所有必要的类型谢谢你的标题更新。