以前访问XML值,同时从生成的模式验证XML文件(Accessing previous xml va

2019-10-20 06:55发布

我想写一个动态的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的验证值

希望稍微清除它。 将被允许

Answer 1:

我不知道,如果你想生成每个文件一个模式或者一个模式来验证他们。 第二种情况在我看来是最好的选择,但因为你的例子只显示一个简单的类型,你可能需要不同的东西。 在任何情况下,我包括在这个答案两种选择。

在这两种情况下,我假设你有几个文件bean-choice-1.xmlbean-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该文件的(假设路径是唯一的)。

该字符串(它将包含12 -在你的例子)将被用来建立一个字符串(串联bean12 ),将与其相比拟的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-1beanString-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.xmlbean-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
标签: xml xslt xsd