我正在尝试编写一个动态xml架构,该架构将根据xml中的先前条目针对不同的源验证xml文件。
我目前正在使用xslt和spring beans文件生成xsd架构。这意味着我可以根据spring配置设置限制。我在根据以前的输入更改引用哪个bean时遇到问题。
我的(简化)bean文件(不必使用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>
有没有办法做到这一点?
由于
编辑: 为了尝试清除任何混淆,bean的选择应该来自生成的模式正在验证的文件。所以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的验证值
不匹配希望稍微清理一下。 将被允许
答案 0 :(得分:0)
我不确定您是要为每个文件生成一个模式还是单一模式来验证所有这些模式。第二种情况在我看来是最好的选择,但由于你的例子只显示了一种简单的类型,你可能想要一些不同的东西。无论如何,我在这个答案中都包含了两种选择。
在这两种情况下,我假设您有几个文件bean-choice-1.xml
,bean-choice-2.xml
,每个文件都包含您希望使用生成的模式验证的数据(我假设这些文件完全具有XML你包含在你的问题中(我将使用路径/toValidate/beanChoice
)。
XSLT处理器将使用beans.xml
文件作为输入。您可以将希望从中提取数据的另一个文件的名称作为参数传递给XSLT处理器,XSLT处理器也可以加载并解析它。
参数传递取决于实现。它的工作原理取决于您运行处理器的方式(命令行,编程语言等)。您还可以硬连线样式表中的参数(如果在运行时传递新参数,则可以覆盖该参数处理器)。
例如,在命令行上运行Saxon,您可以在最终参数处传递参数:
java net.sf.saxon.Transform -s:beans.xml -xsl:stylesheet.xsl -o:schema-1.xsd bean-file=bean-choice-2.xml
上面的行设置了一个包含bean-file
的{{1}}参数,该参数将设置(或覆盖)样式表中使用顶级 bean-choice-2.xml
声明的参数。您还可以运行处理器并使用Java,C#,Python,Ruby,PHP等编程语言设置其参数。
以下XSLT样式表使用<xsl:param>
函数,该函数解析由URI(存储在document()
)中定位的XML文档,并允许在样式表中处理其节点。它将使用作为参数传递的文件名作为相对URI(如果未传递参数,则使用默认值)。
<xsl:param>
变量存储解析文件后获得的值,并提取存储在该文件的路径bean-choice
中的值(假设路径是唯一的)。
该字符串(在您的示例中将包含/toValidate/beanChoice
或1
)将用于构建字符串(将2
与bean
或{{1}连接起来})将与其他bean的1
属性进行比较。正则表达式将从匹配的正则表达式中提取:
2
如果您使用其他文件,您将在该简单类型声明中获得包含不同模式的XML Schema。
上面包含的样式表会为每个文件生成一个模式。我不确定这对你来说是理想的情况。通常最好为许多类似文件使用一个模式,重用不同元素中的类型(即使您稍后将其用作特定方案中的导入模式)。对于这种情况,您必须以某种方式识别您的简单类型,以便以不同方式命名它们。你可以像这样生成一个简单类型名为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>
的XSD:
beanString-1
您可能已经知道从中提取数据所需的所有文件,因此您可以在样式表中列出它们,而不是传递参数。在下面的XSLT中,这些文件包含在具有任意命名空间的嵌入式文档中(使用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>
,嵌入式文档可以在myns
中访问,因此我们可以使用它来处理每个文件名的模板,添加一个新的{每种情况下都有{1}}个元素。
此XSLT用于生成上面的XSD,使用document('')
文件作为输入,文件/*/myns:files
和<xsd:simpleType>
(包含与您问题中的示例相同的数据)在同一目录中:
beans.xml