XSL转换 - 如何查找链接节点

时间:2015-03-09 20:30:01

标签: xml xslt transformation

我是XSL转换的新手。我正在将以下XML转换为另一种XML格式:

<root>

 <header>
   <section id="a1">
     <color>red</color>
   </section>

   <section id="a2">
     <color>blue</color>
   </section>

 </header>

 <body>
   This is the sample text <reference link="a1">with color red</reference> 
   and <reference link="a2">with color blue</reference>
 </body> 

</root>

section id(在标题中)链接到引用链接(在正文中)。我必须寻找颜色&#39;蓝色&#39;在<color>节点中。如果它可用,那么我必须删除父<section>节点。除此之外,&#39; id&#39;该部分是&#34; a2&#34;。必须删除正文中相应的参考链接。结果:

<root>

 <header>
   <section id="a1">
     <color>red</color>
   </section>

 </header>

 <body>
   This is the sample text <reference link="a1">with color red</reference> 
   and with color blue
 </body> 

</root>

任何人都可以提供一些关于如何开始的提示吗?

1 个答案:

答案 0 :(得分:3)

您应该能够获得@id部分的blue,然后删除section和&#34;展开&#34; reference

以下是2个例子。一个在XSLT 1.0中,一个在XSLT 2.0中。

XSLT 1.0

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

    <xsl:param name="toStrip" select="'blue'"/>
    <xsl:variable name="stripRef" select="//section[color=$toStrip]/@id"/>

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

    <xsl:template match="header">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()[not(self::section[@id=$stripRef])]"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="reference">
        <xsl:choose>
            <xsl:when test="@link=$stripRef">
                <xsl:apply-templates/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:apply-templates select="@*|node()"/>
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

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="toStrip" select="'blue'"/>
    <xsl:variable name="stripRef" select="//section[color=$toStrip]/@id"/>

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

    <xsl:template match="section[@id=$stripRef]"/>

    <xsl:template match="reference[@link=$stripRef]">
        <xsl:apply-templates/>
    </xsl:template>    

</xsl:stylesheet>

基于评论的编辑

这是一种可以处理多个ID的方法。由于toStrip param不能是一个序列,我们需要添加一个字符来分隔这些值。在这个例子中,我使用了|。这样contains()在将a1a10等内容进行比较时不会成为现实。

此外,XSLT 1.0仅返回@id变量select中的第一个stripRef。为了获得所有ID,我添加了xsl:for-each。您也可以使用模式使用xsl:apply-templates执行此操作。

这里是更新的XSLT:

XSLT 1.0

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

    <xsl:param name="toStrip" select="'|blue|orange|'"/>
    <xsl:variable name="stripRef">
        <xsl:text>|</xsl:text>
        <xsl:for-each select="//section[color[contains($toStrip,concat('|',.,'|'))]]/@id">
            <xsl:value-of select="concat(.,'|')"/>
        </xsl:for-each>
    </xsl:variable>

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

    <xsl:template match="header">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()[not(self::section[contains($stripRef,concat('|',@id,'|'))])]"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="reference">
        <xsl:message>contains(<xsl:value-of select="$stripRef"/>,<xsl:value-of select="concat('|',@link,'|')"/>)</xsl:message>
        <xsl:choose>
            <xsl:when test="contains($stripRef,concat('|',@link,'|'))">
                <xsl:apply-templates/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:apply-templates select="@*|node()"/>
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

要在XSLT 2.0中执行相同的操作,您只需将toStrip参数更改为序列:

<xsl:param name="toStrip" select="('blue','orange')"/>