根据属性(XSLT)

时间:2016-09-11 14:39:40

标签: xml xslt xpath xslt-2.0

这个问题让我头疼了很长一段时间。让我们来看看吧。

我正在处理的文件:

<?xml version="1.0" encoding="UTF-8"?>
<Message>
    <Specification>
        <!--1.-->
        <Fruit>
            <!--1.1-->
            <Apple/>
            <!--1.2-->
            <Separator/>
            <!--1.3-->
            <Orange/>
            <!--1.4-->
            <SeperatorCLRF/>
        </Fruit>
        <!--2.-->
        <Cookie>
            <!--2.1-->
            <Dough/>
            <!--2.2-->
            <Separator/>
            <!--2.3-->
            <Chocolate>
                <!--2.3.1-->
                <Crisp/>
                <!--2.3.2-->
                <Chunk/>
            </Chocolate>
            <!--2.4-->
            <SeparatorCLRF/>
        </Cookie>
    </Specification>
    <Repetitions>
        <Repeat_1 begin="2.2 " end="2.3.2" amount="5"/>
        <Repeat_2 begin="2.2 " end="2.4"/>
    </Repetitions>
</Message>

我们的想法是将此XML转换为适当的XSD。子元素(例如1.x和1.x.x)将被赋予其自己的复杂类型并相应地引用。然而,重要的是在&#34;重复&#34;下找到的参考文献。找到并且也给出了他们自己的复杂类型,以便我能够告诉:&#34;这些元素可以重复无限次。&#34;或者&#34;这些元素可以重复这个次。&#34;

由于我刚刚开始编写XSL文件,以下代码段可能有点太长了,我道歉。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="3.0">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
            <xs:element name="Message" type="Specification"/>
            <xsl:apply-templates/>
        </xs:schema>
    </xsl:template>

    <xsl:template match="Specification">
        <xs:complexType name="Specification">
            <xs:sequence>
                <xsl:apply-templates select="//Specification/*" mode="references"/>
            </xs:sequence>
        </xs:complexType>
        <xsl:apply-templates select="//Specification/*" mode="data"/>
        <xsl:apply-templates select="//Specification/*" mode="subdata"/>
    </xsl:template>

    <xsl:template match="//Specification/*" mode="references">
        <xs:element>
            <xsl:attribute name="name" select="local-name()"/>
            <xsl:attribute name="type" select="local-name()"/>
        </xs:element>
    </xsl:template>

    <xsl:template match="//Specification/*" mode="data">
        <xs:complexType name="{local-name()}">
            <xs:sequence>
                <xsl:for-each select="*">
                    <xs:element>
                        <xsl:attribute name="name" select="local-name()"/>
                        <xsl:choose>
                            <xsl:when test="*">
                                <xsl:attribute name="type"
                                    select="concat(name(..),'_', local-name())"/>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:attribute name="type">xs:string</xsl:attribute>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xs:element>
                </xsl:for-each>
            </xs:sequence>
        </xs:complexType>

    </xsl:template>

    <xsl:template match="//Specification/*" mode="subdata">
        <xsl:variable name="current_name" select="local-name()"/>
        <xsl:for-each select="*">
            <xsl:if test="*">
                <xs:complexType>
                    <xsl:attribute name="name" select="concat($current_name,'_', local-name())"/>
                    <xs:sequence>
                        <xsl:for-each select="*">
                            <xs:element>
                                <xsl:attribute name="name" select="local-name()"/>
                                <xsl:attribute name="type">xs:string</xsl:attribute>
                            </xs:element>
                        </xsl:for-each>
                    </xs:sequence>
                </xs:complexType>
            </xsl:if>
        </xsl:for-each>

    </xsl:template>
</xsl:stylesheet>

结果如下XSD:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="Message" type="Specification"/>
    <xs:complexType name="Specification">
        <xs:sequence>
            <xs:element name="Fruit" type="Fruit"/>
            <xs:element name="Cookie" type="Cookie"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="Fruit">
        <xs:sequence>
            <xs:element name="Apple" type="xs:string"/>
            <xs:element name="Separator" type="xs:string"/>
            <xs:element name="Orange" type="xs:string"/>
            <xs:element name="SeperatorCLRF" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="Cookie">
        <xs:sequence>
            <xs:element name="Dough" type="xs:string"/>
            <xs:element name="Separator" type="xs:string"/>
            <xs:element name="Chocolate" type="Cookie_Chocolate"/>
            <xs:element name="SeparatorCLRF" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="Cookie_Chocolate">
        <xs:sequence>
            <xs:element name="Crisp" type="xs:string"/>
            <xs:element name="Chunk" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

几点说明:

  1. &#34;规范&#34;的后代永远不同。因此使用&#39; / *&#39;。
  2. 1.x.x是最大深度。
  3. 评论将始终存在(不确定是否重要),并且可以用来解决问题。
  4. 重复有一定数量的子项(重复),但它们都遵循相同的格式:开始,结束和可选金额。开始和结束都可以是:x。 x.x x.x.x 其中 x代表一个数字。
  5. 上述beginend将始终正确排序。换句话说,end中的引用将始终位于begin中的引用之后。
  6. 如您所见,XSD尚未包含重复内容。目的是得到这个:

    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xs:element name="Message" type="Specification"/>
        <xs:complexType name="Specification">
            <xs:sequence>
                <xs:element name="Fruit" type="Fruit"/>
                <xs:element name="Cookie" type="Cookie"/>
            </xs:sequence>
        </xs:complexType>
        <xs:complexType name="Fruit">
            <xs:sequence>
                <xs:element name="Apple" type="xs:string"/>
                <xs:element name="Separator" type="xs:string"/>
                <xs:element name="Orange" type="xs:string"/>
                <xs:element name="SeperatorCLRF" type="xs:string"/>
            </xs:sequence>
        </xs:complexType>
        <xs:complexType name="Cookie">
            <xs:sequence>
                <xs:element name="Dough" type="xs:string"/>
                <xs:element name="Repeat_2" type="Repeat_2" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
        <xs:complexType name="Cookie_Chocolate">
            <xs:sequence>
                <xs:element name="Crisp" type="xs:string"/>
                <xs:element name="Chunk" type="xs:string"/>
            </xs:sequence>
        </xs:complexType>
        <xs:complexType name="Repeat_2">
            <xs:sequence>
                <xs:element name="Repeat_1" type="Repeat_1" maxOccurs="5"/>
                <xs:element name="SeparatorCLRF" type="xs:string"/>
            </xs:sequence>
        </xs:complexType>
        <xs:complexType name="Repeat_1">
            <xs:sequence>
                <xs:element name="Separator" type="xs:string"/>
                <xs:element name="Chocolate" type="Cookie_Chocolate"/>
            </xs:sequence>
        </xs:complexType>
    </xs:schema>
    

    我必须解决问题的想法如下:在逐步通过节点时,不断检查是否可以在重复中找到当前节点。如果找到begin属性,请通过使用起始标记开始包装元素。然后在找到end属性后,关闭标记。

    类似的东西:

    <xsl:variable name="currentNode" select="preceding-sibling::comment()[1]"/>
    
    <xsl:for-each select="//Repetitions/Repeat">
        <xsl:choose>
                <xsl:if test="$currentNode = @begin">
                    <complexType>
                </xsl:if>
                <xsl:if test="$currentNode = @end">
                    </complexType>
                </xsl:if>  
        </xsl:choose>
    </xsl:for-each>
    

    上面的示例应该说明我尝试使用起始和结束标记。显然这不起作用,因为你必须在if语句中终止标记。

    我想,最大的问题是包装重复元素&#34;有点破坏了XSLT的其余部分。啊!

    我完全陷入了这一点,因为我一直在想要开始一个标签然后结束标签的问题上磕磕绊绊。这对我来说是唯一合乎逻辑的东西,但这是不可能做到的。也许这纯粹是通过使用XSLT来解决的。

    希望有人能把我送到正确的方向!无论如何,谢谢你的阅读。

    EDIT1:我应该可以在XML文件中添加一些额外的数据。可能更容易获得我想要的结果的东西。如果有人读到这篇文章可能知道最好添加什么,请发表评论。

    EDIT2:我开始认为这个问题无法用当前的结构来解决。我尝试在初始XML结构中添加元素,但我一直发现自己陷入了一个问题:实际上包装了重复的块。如果我创建所有complexTypes(就像我在XSLT中所做的那样)之前确定重复块,则无法正确包装,因为重复块的一部分可能必须以complexType结尾#39;已经制作好了。即使我决定先确定重复块,我也会遇到同样的问题。

    真的希望从人们那里得到一些指示或想法。

0 个答案:

没有答案