是否有可能或如何进一步干掉这个XML语句?

时间:2014-06-20 04:55:08

标签: xml xslt dry

从其他人的经验来看,似乎是个案,他们的问题通常是如何干这个或如何干燥...所以在我的情况下,它是类似的东西,而不是一个特殊情况,我试着更广泛地问:

说,我有一个带有以下行的xml代码

<input type="text" defaultValue="" name="Fax_Label" label="Fax Label" />

将被解析,然后使用XSLT进行样式化。

因为我来自CSS,PHP,JS,基于我的PHP经验 我可以创建一个数组和一个这样的循环来完成,所以我可以用模板块分隔参数,例如。

$para_arr = array(
   // type | name | label
   array('text', 'Fax_Text', 'Fax Text')
);

for( $i=0; $i<count($para_arr); $i++){
echo '<input type="{$para_arr[i][0]}" defaultValue="" name="{$para_arr[i][1]}" label="{$para_arr[i][2]}" />';
}

是否有任何XML等效方法来完成相同的事情? 非常感谢。

以上将是这个问题的历史的一部分,让其他人为什么我被投票。 旧问题:如何像使用数组和for循环的PHP一样干XML / XSLT?

此处修订的问题: 干这个结构有可能吗? 因为将有超过30个字段,复制和粘贴所有字段并逐个编辑它是相当繁琐和难以维护的。

<namespace>
    <cms_data>
        <inputGRP>
            <input type="text" defaultValue="" name="nickname_label" label="NickName Label" />
            <input type="text" defaultValue="" name="nickname_error" label="NickName Error" />
            <input type="text" defaultValue="" name="rowTitle_login" label="Row Heading Login" />
            <input type="text" defaultValue="" name="title_label" label="Title Label" />
            <input type="text" defaultValue="" name="title_error" label="Title Error" />
        </inputGRP>
    </cms_data>
</namespace>

3 个答案:

答案 0 :(得分:0)

我将您的问题读作&#34;知道如何将PHP变量放入HTML echo中,如何在XSLT代码中完成此操作,例如在循环中#34;。
要在XSLT中输出XML数据,可以使用数据是XML文件中的实际数据或XSLT变量的xpath。这在HTML属性中不起作用,因为那里不允许使用尖括号。相反,您可以使用属性值模板(AVT,请参阅http://www.w3.org/TR/xslt#attribute-value-templates),写作{data}就像您的PHP示例一样,仅使用xpath(或xslt变量)。
如果我错过了这一点,请不要开枪,我不会说英语。

答案 1 :(得分:0)

我不完全确定这是否是您所要求的,但XSLT本身并没有数组的概念。但是,您可以像这样定义一些XML

<array>
    <array>
        <value>text</value>
        <value>Fax_Label</value>
        <value>Fax Label</value>
    </array>
</array>

然后,对于你的循环&#39;您将采用基于模板的方法,因此请选择&#39;数组&#39;元素

    <xsl:variable name="para_arr" select="/array" />
    <xsl:apply-templates select="$para_arr/array" />

然后模板本身会看起来这个

<xsl:template match="array">
    <input type="{value[1]}" defaultValue="" name="{value[2]}" label="{value[3]}" />
</xsl:template>

请注意,此处使用属性值模板输出值。花括号表示要计算的表达式,而不是字面输出。另请注意,在XSLT中,索引从1开始,而不是0。

如果您将XML定义为此类

,那就更好了
<array>
    <array>
        <value name="type">text</value>
        <value name="name">Fax_Label</value>
        <value name="label">Fax Label</value>
    </array>
</array>

然后可以修改您的XSLT以应对无限数量的属性

试试这个XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output indent="yes"/>
    <xsl:template match="/">
        <xsl:variable name="para_arr" select="/array" />

        <xsl:apply-templates select="$para_arr/array" />
    </xsl:template>

    <xsl:template match="array">
        <input defaultvalue="">
            <xsl:apply-templates select="value" />
        </input>
    </xsl:template>

    <xsl:template match="value">
        <xsl:attribute name="{@name}">
            <xsl:value-of select="." />
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

请注意,上面的XML可以放在要转换的主XML的单独文件中,在这种情况下只需使用document函数来访问它:

<xsl:variable name="para_arr" select="document('myArray.xml')/array" />

答案 2 :(得分:0)

与XSLT具有的数组最接近的结构是序列。一系列原子值,比如字符串,是基本的,所以你需要提出自己的方案来重现类似多维数组的东西。

这是一个我有2个序列的例子。第一个序列是属性名称。第二个序列是值。

第二个序列还需要指定它所属的entry。为了处理这个问题,我在每个值中添加了前缀e#:。例如,第一个entry的条目具有前缀e1:。然后我可以使用这些值将所有内容组合在一起。

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:param name="names" select="('type','defaultValue','name','label')"/>
    <xsl:param name="values" select="('e1:text','e1:','e1:nickname_label','e1:NickName Label',
                                      'e2:text','e2:','e2:nickname_error','e2:NickName Error',
                                      'e3:text','e3:','e3:rowTitle_login','e3:Row Heading Login',
                                      'e4:text','e4:','e4:title_label','e4:Title Label',
                                      'e5:text','e5:','e5:title_error','e5:Title Error'
                                      )"/>

    <xsl:template match="/">
        <namespace>
            <cms_data>
                <inputGRP>            
                    <xsl:for-each-group select="$values" group-by="tokenize(.,':')[1]">
                        <input>
                            <xsl:for-each select="current-group()">
                                <xsl:variable name="pos" select="position()"/>
                                <xsl:attribute name="{$names[$pos]}" select="tokenize(.,':')[2]"/>
                            </xsl:for-each>
                        </input>
                    </xsl:for-each-group>
                </inputGRP>
            </cms_data>
        </namespace>
    </xsl:template>

</xsl:stylesheet>

输出(使用任何格式正确/有效的XML输入。我使用样式表本身进行输入。)

<namespace>
   <cms_data>
      <inputGRP>
         <input type="text"
                defaultValue=""
                name="nickname_label"
                label="NickName Label"/>
         <input type="text"
                defaultValue=""
                name="nickname_error"
                label="NickName Error"/>
         <input type="text"
                defaultValue=""
                name="rowTitle_login"
                label="Row Heading Login"/>
         <input type="text"
                defaultValue=""
                name="title_label"
                label="Title Label"/>
         <input type="text"
                defaultValue=""
                name="title_error"
                label="Title Error"/>
      </inputGRP>
   </cms_data>
</namespace>

我不确定这是否比你现在做的更容易维护。一个优点是通过使用xsl:param,您可以在运行时传递序列。这将允许您维护或生成与XSLT分开的名称和值。