我想写一个动态的XML模式,将取决于在XML以前的条目验证XML文件对不同来源。
我使用XSLT和弹簧豆文件当前生成XSD架构。 这意味着我可以设置基于Spring配置的限制。 我有豆被引用根据之前输入该问题的变化。
我(简体)豆文件(没有使用Spring,如果需要的话可以只是简单的XML):
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="transform.xsl"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd >
<bean id="bean1" class="com.example.package.Class1">
<property name=validation value="[a-zA-Z]">
</bean>
<bean id="bean2" class="com.example.package.Class1">
<property name=validation value="[a-s]+">
</bean>
<bean id="bean3" class="com.example.package.Class1">
<property name=validation value="[a-s]+">
</bean>
</beans>
在transform.xsl文件我试图做类似如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:spring="http://www.springframework.org/schema/beans"
exclude-result-prefixes="spring">
<xsl:output indent="yes" />
<xsl:template match="/">
<xsd:complexType name="toValidate">
<xsd:simpleType name="beanChoice">
<xsd:restriction base="xsd:short">
<xsd:maxInclusive value="3"/>
<xsd:minInclusive value="1"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="beanString">
<xsd:restriction base="xsd:string">
<!---=-=-=-=-Problem here-=-=-=-=-=--->
<xsd:pattern value="if beanChoice==1 then bean1/validation/value
else if beanChoice==2 then bean2/validation/value
else bean3/validation/value"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:complexType>
</xsl:template>
有没有办法做到这一点?
谢谢
编辑:要尝试和消除混淆,豆的选择应来自生成的模式被验证的文件。 所以XSLT文件应该产生,我将用它来验证XML文件的模式。
下列:
<toValidate>
<beanChoice>2</beanChoice>
<!-- this string should be validated against bean2 as the entry for beanChoice was 2-->
<beanString>abc</beanString>
</toValidate>
将是有效的
但
<toValidate>
<beanChoice>1</beanChoice>
<!-- this string should be validated against bean1 as the entry for beanChoice was 1-->
<beanString>abc</beanString>
</toValidate>
不会,因为它不符合bean1的验证值
希望稍微清除它。 将被允许
我不知道,如果你想生成每个文件一个模式或者一个模式来验证他们。 第二种情况在我看来是最好的选择,但因为你的例子只显示一个简单的类型,你可能需要不同的东西。 在任何情况下,我包括在这个答案两种选择。
在这两种情况下,我假设你有几个文件bean-choice-1.xml
, bean-choice-2.xml
,每一个都包含您希望与生成的模式验证数据(我假设文件具有完全相同的XML你纳入你的问题(这里我将使用路径/toValidate/beanChoice
)。
1.产生包含每个文件一个简单类型一个模式
XSLT处理器将使用beans.xml
文件作为输入。 你可以通过从你希望将数据作为参数传递给XSLT处理器,该处理器还可以加载并解析其解压缩到XSLT另一个文件的名称。
参数传递是依赖于实现。 它是如何工作取决于你如何运行你的处理器(命令行,编程语言等),还可以硬连线在样式表(可如果你通过一个新的参数,当您运行的处理器被覆盖)的参数。
例如,运行撒克逊在命令行中,你可以通过在最后参数的参数:
java net.sf.saxon.Transform -s:beans.xml -xsl:stylesheet.xsl -o:schema-1.xsd bean-file=bean-choice-2.xml
上面的行设置一个bean-file
包含参数bean-choice-2.xml
将设置(或覆盖)与顶层声明的参数<xsl:param>
在样式表中。 您也可以运行在处理器和与编程语言如Java,C#,Python和Ruby,PHP等设置参数
下面XSLT样式表使用document()
函数,该函数解析位于由URI一个XML文档(存储在<xsl:param>
并允许其节点在样式表中被处理。 它将使用,作为一个相对URI,作为参数传递的文件名 (或使用默认值 ,如果没有参数传递)。
所述bean-choice
解析文件,并提取存储在路径中的值后得到的值变量存储/toValidate/beanChoice
该文件的(假设路径是唯一的)。
该字符串(它将包含1
或2
-在你的例子)将被用来建立一个字符串(串联bean
有1
或2
),将与其相比拟的id
其他豆类的属性。 正则表达式将匹配一个提取:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:spring="http://www.springframework.org/schema/beans"
exclude-result-prefixes="spring">
<xsl:output indent="yes"/>
<!-- You can set/reset this parameter when running your XSLT processor -->
<xsl:param name="bean-file">bean-choice-2.xml</xsl:param>
<xsl:variable name="bean-choice" select="document($bean-file)/toValidate/beanChoice"/>
<xsl:template match="/">
<xsd:schema elementFormDefault="qualified">
<xsd:simpleType name="beanChoice">
<xsd:restriction base="xsd:string">
<xsd:maxInclusive value="3"/>
<xsd:minInclusive value="1"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="beanString">
<xsd:restriction base="xsd:string">
<xsd:pattern ref="{//spring:bean[@id=concat('bean',$bean-choice)]/spring:property[@name='validation']/@value}" />
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
</xsl:template>
</xsl:stylesheet>
如果你使用一个不同的文件,你会得到包含简单类型声明不同模式的XML模式。
2.生成具有多个简单类型单个模式
我上面所包括的样式表会产生每个文件一个架构 。 我不知道它这是您理想的情况。 它通常是更好的有很多类似的文件一个模式,重新使用不同元素的类型(即使你后来在特定情况下使用它作为一个导入的架构)。 对于这样的情况,你会以某种方式识别 ,以不同的方式命名他们的简单类型。 你可能会产生这样一个地方的简单类型命名为XSD beanString-1
和beanString-2
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xsd:simpleType name="beanChoice">
<xsd:restriction base="xsd:string">
<xsd:maxInclusive value="3"/>
<xsd:minInclusive value="1"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="beanString-1">
<xsd:restriction base="xsd:string">
<xsd:pattern ref="[a-zA-Z]"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="beanString-2">
<xsd:restriction base="xsd:string">
<xsd:pattern ref="[a-s]+"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
你可能已经知道你需要从数据中提取文件,因此而不是传递参数,你可以在样式表中列出。 在下面的XSLT,这些文件都包含任意命名空间的嵌入文档中(使用myns
作为前缀)。 样式表本身可被加载为document('')
和嵌入的文档是在访问/*/myns:files
,所以我们可以用它来处理每个文件名称的模板,添加一个新的<xsd:simpleType>
在元件每个案例。
此XSLT用于产生上面的XSD,使用beans.xml
文件作为文件输入bean-choice-1.xml
和bean-choice-2.xml
位于(包含相同的数据从你的问题的样品)同一个目录下:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:myns="input-file-list"
exclude-result-prefixes="spring myns">
<xsl:output indent="yes"/>
<myns:files>
<name>bean-choice-1.xml</name>
<name>bean-choice-2.xml</name> <!-- you can add more file names -->
</myns:files>
<xsl:template match="/">
<xsd:schema elementFormDefault="qualified">
<xsd:simpleType name="beanChoice">
<xsd:restriction base="xsd:string">
<xsd:maxInclusive value="3"/>
<xsd:minInclusive value="1"/>
</xsd:restriction>
</xsd:simpleType>
<xsl:apply-templates select="document('')/*/myns:files/name">
<xsl:with-param name="spring-beans" select="//spring:bean" />
</xsl:apply-templates>
</xsd:schema>
</xsl:template>
<!-- This template is processed for each file -->
<xsl:template match="myns:files/name">
<xsl:param name="spring-beans"/> <!-- this contains the collection of beans from the beans.xml file -->
<xsl:variable name="bean-choice" select="document(.)/toValidate/beanChoice"/>
<xsd:simpleType name="beanString-{$bean-choice}">
<xsd:restriction base="xsd:string">
<xsd:pattern ref="{$spring-beans[@id=concat('bean',$bean-choice)]/spring:property[@name='validation']/@value}" />
</xsd:restriction>
</xsd:simpleType>
</xsl:template>
</xsl:stylesheet>
文章来源: Accessing previous xml values while validating the xml file from generated schema