使用XSLT将XML标记转换为任意位置的属性

时间:2010-12-16 17:47:28

标签: xml xslt xpath xslt-2.0

我们有一种XML格式,实际上只是带有一些额外gubbins的HTML。它定义了哪些HTML元素是可编辑的,哪些属性可以编辑。

这是一个例子

<img src="images/placeholder.jpg" 
     alt="Placeholder" 
     width="600" 
     height="250" 
     border="0">
  <var attr="src" />
  <var attr="height" ok="150-300" />
</img>

XML是如此模板更容易编写,但我需要将其转换为有效(ish)HTML。要做到这一点,我想把它折叠成:

<img src="images/placeholder.jpg" 
     alt="Placeholder" 
     width="600" 
     height="250" 
     border="0"
     editable="src height" 
     constraints="height:150-300">

我可以为<img>执行此操作,但问题是<var>标记实际上可以显示为页面中任何元素的子元素。在所有情况下,将其转换为属性的算法都是相同的,但我无法弄清楚如何做的是指定一个可以匹配<var>标记的父元素的XSLT模板。我试过了match="var/..",但事实证明这是无效的。

另一种方法是匹配<var>并将它们作为属性添加到父母身上,但我相信在此过程中,特定船舶已经航行了。

这可行吗?

Thankies

答案!

我将更完整的答案与Dimitre有用的准确答案结合起来形成以下内容:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="*[var]">
        <xsl:copy >
            <xsl:attribute name="editable">
                <xsl:for-each select="var[@attr]">
                    <xsl:value-of
                        select="concat(@attr,
                            substring(' ',
                                1 div (position()!=last())))"/>
                </xsl:for-each>
            </xsl:attribute>
            <xsl:attribute name="constraints">
                <xsl:for-each select="var[@ok]">
                    <xsl:value-of
                        select="concat(@attr,':',@ok,
                            substring(';',
                                1 div (position()!=last())))"/>
                </xsl:for-each>
            </xsl:attribute>
            <xsl:apply-templates select="@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="var">
    </xsl:template>

    <xsl:template match="@*|node()">
       <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

不幸的是,亚历杭德罗给出的确切答案并没有立即起作用(仍然不确定原因),但他的答案和德米特里的答案的这种组合似乎很好地完成了这项工作:)

3 个答案:

答案 0 :(得分:4)

  

我无法解决的问题是   指定可以的XSLT模板   匹配<var>的父元素   标签

使用

<xsl:template match="*[var]">

答案 1 :(得分:1)

我会考虑构建一个局部变量(<xsl:variable>),因为解析器会转到<img>标记,并在该变量中明确构建一个新的<img ...>,遍历任何<var>它找到的子项(<xsl:foreach ...>任何人?)当变量耗尽时关闭变量...然后将变量写出来?

答案 2 :(得分:1)

除了Dimitre对你的问题的确切答案,其他方法是:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|var"/>
            <xsl:apply-templates select="node()[not(self::var)]"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="var"/>
    <xsl:template match="var[1]">
        <xsl:attribute name="editable">
            <xsl:for-each select="../var/@attr">
                <xsl:value-of
                     select="concat(.,
                                    substring(' ',
                                              1 div (position()!=last())))"/>
            </xsl:for-each>
        </xsl:attribute>
        <xsl:attribute name="constraints">
            <xsl:for-each select="../var/@ok">
                <xsl:value-of
                     select="concat(../@attr,':',.,
                                    substring(';',
                                              1 div (position()!=last())))"/>
            </xsl:for-each>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

输出:

<img src="images/placeholder.jpg" 
     alt="Placeholder" 
     width="600" 
     height="250" 
     border="0" 
     editable="src height" 
     constraints="height:150-300"></img>