0

我在输入文件中有两个标签,变量和类型:

<variable baseType="int" name="X">
</variable>

<type baseType="structure" name="Y">
    <variableInstance name="X" />
</type>

我需要生成以下输出文件:

<Item name="Y">
    <Field name="X" type="Long" />
</Item>

所以从概念上讲,我的方法是将类型标签转换为项目标签,将变量实例转换为字段。这工作正常:

<xsl:for-each select="type[@baseType='structure']">
    <Item>
        <xsl:attribute name="name"><xsl:value-of select="@name" /></xsl:attribute>
        <xsl:for-each select="variableInstance">
            <Field>
                <xsl:attribute name="name"><xsl:value-of select="@name" /></xsl:attribute>
                <xsl:attribute name="type">**THIS IS WHERE I'M STUCK**</xsl:attribute>
            </Field>
        </xsl:for-each>
    </Item>
</xsl:for-each>

我坚持的问题是:

  1. 我不知道如何让 variableInstance/Field 标记按名称与变量标记匹配,因此我可以访问 baseType。
  2. 一旦我能够做到1,我需要将“int”映射到“Long”。

提前致谢!

4

2 回答 2

1

问题1。

对于您遇到的第一个问题,您可以使用密钥:

<xsl:key name="variable-key" match="//variable" use="@name" />

该键将使用它们的名称索引文档中的所有变量元素。所以现在,我们可以使用以下 XPath 表达式访问这些元素中的任何一个:

key('variable-key', 'X')

当您有很多可变元素时,使用这种方法是有效的。

注意:如果每个变量都有自己的范围(即您有在文档的不同部分不可见的局部变量),则此方法无效。在这种情况下,应该修改这种方法。

问题 2。

对于映射属性,您可以使用如下模板:

    <xsl:template match="@baseType[. = 'int']">
        <xsl:attribute name="baseType">
            <xsl:value-of select="'Long'" />
        </xsl:attribute>
    </xsl:template>

这个转换的意思是:每次我们匹配一个baseType属性和int值,它都必须被一个Long值替换。

对于文档中的每个 @baseType 属性,都将进行此转换。


使用所描述的策略,解决方案可能是:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes" />

    <!-- Index all variable elements in the document by name -->
    <xsl:key name="variable-key"
             match="//variable"
             use="@name" />

    <!-- Just for demo -->
    <xsl:template match="text()" />

    <!-- Identity template: copy attributes by default -->
    <xsl:template match="@*">
        <xsl:copy>
            <xsl:value-of select="." />
        </xsl:copy>
    </xsl:template>

    <!-- Match the structure type -->
    <xsl:template match="type[@baseType='structure']">
        <Item>
            <xsl:apply-templates select="*|@*" />
        </Item>
    </xsl:template>

    <!-- Match the variable instance -->
    <xsl:template match="variableInstance">
        <Field>
            <!-- Use the key to find the variable with the current name -->
            <xsl:apply-templates select="@*|key('variable-key', @name)/@baseType" />
        </Field>
    </xsl:template>

   <!-- Ignore attributes with baseType = 'structure' -->
    <xsl:template match="@baseType[. = 'structure']" />

    <!-- Change all baseType attributes with long values to an attribute
        with the same name but with an int value  -->
    <xsl:template match="@baseType[. = 'int']">
        <xsl:attribute name="baseType">
            <xsl:value-of select="'Long'" />
        </xsl:attribute>
    </xsl:template>

</xsl:stylesheet>

该代码将转换以下 XML 文档:

<!-- The code element is present just for demo -->
<code>
    <variable baseType="int" name="X" />
    <type baseType="structure" name="Y">
        <variableInstance name="X" />
    </type>
</code>

进入

<Item name="Y">
    <Field baseType="Long" name="X"/>
</Item>
于 2013-02-25T15:40:19.960 回答
0

Oki 我有第 1 点xsltcake 切片使用模板的解决方案。对于第二点,我可能会使用与 Pablo Pozo 在他的回答中使用的模板类似的模板

于 2013-02-25T16:05:40.817 回答