如何在一个xml节点上应用多个xsl-templates [英] How to apply more then one xsl-templates on one xml node

查看:98
本文介绍了如何在一个xml节点上应用多个xsl-templates的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的问题:

我有HTML文档和CSS样式。我需要将这些样式移动到主体中的元素中,并将它们从样式标记中移除。



我为每个CSS样式和值创建了xpath的帮助器,放在那里。然后它生成XSL文档并将其应用于HTML。



有时,需要将多个xsl模板应用于同一个节点(相同匹配) 。



如何将它们全部应用?



以下是HTML的一个例子:

 < html lang =en> 
< head>
< META HTTP-EQUIV =Content-TypeCONTENT =text / html; CHARSET = utf-8/>
< style type =text / css>
.right-aligned {text-align:right!important; }
.full-width {width:100%!important;显示:inline-block; }
< / style>
< / head>
< body>
< table class =header>
< tr>
< td class =icon>
< img alt =次要src =Picture_SRC/>
< / td>
< td>
< div class =辅助全角右对齐> Blah:测试< / div>
< / td>
< / tr>
< / table>
< / body>
< / html>

还有需要为这个HTML完成的XSL转换:

 < xsl:template match =// * [contains(@ class,'right-aligned')and @style]> 
< xsl:attribute name =style>
< xsl:value-of select =concat(。,'text-align:right!important;')/>
< / xsl:attribute>
< / xsl:template>
< xsl:copy>
< xsl:attribute name =style> text-align:right!important;< / xsl:attribute>
< xsl:apply-templates select =@ * | node()/>
< / xsl:copy>
< / xsl:template>
< xsl:template match =// * [contains(@ class,'full-width')and @style]>
< xsl:attribute name =style>
< xsl:value-of select =concat(。,'width:100%!important; display:inline-block;')/>
< / xsl:attribute>
< / xsl:template>
< xsl:copy>
< xsl:apply-templates select =@ * | node()/>
< / xsl:copy>
< / xsl:template>

重要的事情是:HTML不是静态的,它会改变...所以我不能让静态XSL。

解决方案

以下是您可以使用模式 $ c $> www.w3.org/1999/XSL/Transformversion =1.0>

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

< xsl:template match =@ class>
< xsl:attribute name =style>
< xsl:value-of select =@ style/>
< xsl:text> ;;< / xsl:text>
< / xsl:if>
< / xsl:attribute>
< / xsl:template>

< xsl:template match =@ style/>

< xsl:if test =contains(。,'right-align')>
< xsl:text> text-align:right!important;< / xsl:text>
< / xsl:if>
< / xsl:template>

< xsl:if test =contains(。,'full-width')>
< xsl:text>宽度:100%!重要; display:inline-block;< / xsl:text>
< / xsl:if>
< / xsl:template>
< / xsl:stylesheet>

如果您可以使用XSLT 2.0,则可以使用优先级而不是模式来简化此操作, xsl:next-match 可以找到下一个匹配模板,优先级较低。

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

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

< xsl:template match =@ classpriority =10>
< xsl:attribute name =style>
< xsl:value-of select =@ style/>
< xsl:text> ;;< / xsl:text>
< / xsl:if>
< xsl:next-match />
< / xsl:attribute>
< / xsl:template>

< xsl:template match =@ style/>

< xsl:text> text-align:right!important;< / xsl:text>
< xsl:next-match />
< / xsl:template>

< xsl:text>宽度:100%!重要; display:inline-block;< / xsl:text>
< xsl:next-match />
< / xsl:template>

< xsl:template match =@ class/> <! - 停止应用内置模板 - >
< / xsl:stylesheet>


here is my problem:

I have HTML Document with CSS Styles. I need to move these styles into the elements in the body and remove them from style tag.

I made helper that makes xpath for each css style and value which needs to be put there. Then it generates XSL documents and applies it to the HTML.

The thing is sometimes there are multiple xsl-templates that needs to be applied to the same Node (same match). And just the first one is getting applied, others are ignored.

How i can apply them all?

Here is one example of the HTML:

<html lang="en">
<head>
   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=utf-8"/>
   <style type="text/css">
      .right-aligned { text-align: right !important; }
      .full-width { width: 100% !important; display: inline-block; }
   </style>
</head>
<body>
   <table class="header">
      <tr>
         <td class="icon">
            <img alt="Minor" src="Picture_SRC" />
         </td>
            <td>
               <div class="secondary full-width right-aligned">Blah: Test</div>
            </td>
         </tr>
      </table>
   </body>
</html>

And there is the XSL Transformations that needed to be done for this HTML:

<xsl:template match="//*[contains(@class,'right-aligned') and @style]">
   <xsl:attribute name="style">
      <xsl:value-of select="concat(., 'text-align: right !important;')"/>
   </xsl:attribute>
</xsl:template>
<xsl:template match="//*[contains(@class,'right-aligned') and not(@style)]">
   <xsl:copy>
      <xsl:attribute name="style">text-align: right !important;</xsl:attribute>
      <xsl:apply-templates select="@*| node()"/>
   </xsl:copy>
</xsl:template>
<xsl:template match="//*[contains(@class,'full-width') and @style]">
   <xsl:attribute name="style">
      <xsl:value-of select="concat(., 'width: 100% !important; display: inline-block;')"/>
    </xsl:attribute>
</xsl:template>
<xsl:template match="//*[contains(@class,'full-width') and not(@style)]">
   <xsl:copy>
      <xsl:attribute name="style">width: 100% !important; display: inline-block;</xsl:attribute>
      <xsl:apply-templates select="@*| node()"/>
   </xsl:copy>
</xsl:template>

Important thing: the HTML is not static and it changes ... so i can't make static XSL.

解决方案

Here is one way you could do it, by use of mode attributes, to apply each template one after another

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

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

  <xsl:template match="@class">
    <xsl:attribute name="style">
      <xsl:if test="@style">
        <xsl:value-of select="@style" />
        <xsl:text>;</xsl:text>
      </xsl:if>
      <xsl:apply-templates select="." mode="right-aligned" />
    </xsl:attribute>
  </xsl:template>

  <xsl:template match="@style" />

  <xsl:template match="@class" mode="right-aligned">
    <xsl:if test="contains(.,'right-aligned')">
      <xsl:text>text-align: right !important;</xsl:text>
    </xsl:if>
    <xsl:apply-templates select="." mode="full-width" />
  </xsl:template>

  <xsl:template match="@class" mode="full-width">
    <xsl:if test="contains(.,'full-width')">
      <xsl:text>width: 100% !important; display: inline-block;</xsl:text>
    </xsl:if>
  </xsl:template>  
</xsl:stylesheet>

If you could use XSLT 2.0, you could simplify this by use of priorities, instead of modes, and xsl:next-match to find the next matching template with a lower priority.

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

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

  <xsl:template match="@class" priority="10">
    <xsl:attribute name="style">
      <xsl:if test="@style">
        <xsl:value-of select="@style" />
        <xsl:text>;</xsl:text>
      </xsl:if>
      <xsl:next-match />
    </xsl:attribute>
  </xsl:template>

  <xsl:template match="@style" />

  <xsl:template match="@class[contains(.,'right-aligned')]" priority="9">
    <xsl:text>text-align: right !important;</xsl:text>
    <xsl:next-match />
  </xsl:template>

  <xsl:template match="@class[contains(.,'full-width')]" priority="8">
    <xsl:text>width: 100% !important; display: inline-block;</xsl:text>
    <xsl:next-match />
   </xsl:template>  

  <xsl:template match="@class" /> <!-- Stop the built-in template applying -->
</xsl:stylesheet>

这篇关于如何在一个xml节点上应用多个xsl-templates的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆