2013-02-23 119 views
3

我是XSLT新手,所以我非常感谢任何帮助。 我在stackoverflow上搜索了很多,试图应用几种方法,但失败了。根据其他属性值替换xml属性

我有一个这样的XML:

<?xml version="1.0" encoding="utf-8"?> 
     <asset_detail> 
      <asset id="1" show_type="Movies"> 
      <title><![CDATA[Movie]]></title> 
      <media_list> 
       <media id="11" title="" type="trailer"> 
       <version format="m3u8" rel_path="/Content/movie.m3u8"/> 
       <version format="HLS" rel_path="/movies/movie.m3u8"/> 
       </media> 
       </media_list> 
      </asset> 
     </asset_detail> 

我应该复制整个XML和:

if media_list/media/version/@format = '**HLS**' I need to replace **@rel_path** with 
value: **concat**(existing value of **@rel_path****,** **someVariable** 
(I'm passing to xsl as a <xsl:param>) 

我想我必须使用类似:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="@*|node()"> 
     <xsl:param name="someVariable"/> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="media/version"> 
     <xsl:attribute name="rel_path"> 
      <xsl:choose> 
       <xsl:when test="./@format = HLS"> 
        <xsl:value-of select="concat(rel_path,$someVariable)"> 
       </xsl:when> 
      </xsl:choose> 
     </xsl:attribute> 
    </xsl:template> 
</xsl:stylesheet> 

我知道它不起作用:)

回答

7

较短的解决方案,使用AVT(属性值模板):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 
<xsl:param name="psomeParam" select="'/xxx'"/> 

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

<xsl:template match="version[@format='HLS']"> 
    <version rel_path="{@rel_path}{$psomeParam}"> 
    <xsl:apply-templates select="@*[not(name()='rel_path')] | node()"/> 
    </version> 
</xsl:template> 
</xsl:stylesheet> 

当所提供的XML文档被应用于这种转变:

<asset_detail> 
    <asset id="1" show_type="Movies"> 
     <title><![CDATA[Movie]]></title> 
     <media_list> 
      <media id="11" title="" type="trailer"> 
       <version format="m3u8" rel_path="/Content/movie.m3u8"/> 
       <version format="HLS" rel_path="/movies/movie.m3u8"/> 
      </media> 
     </media_list> 
    </asset> 
</asset_detail> 

有用,正确结果产生:

<asset_detail> 
    <asset id="1" show_type="Movies"> 
     <title>Movie</title> 
     <media_list> 
     <media id="11" title="" type="trailer"> 
      <version format="m3u8" rel_path="/Content/movie.m3u8"/> 
      <version rel_path="/movies/movie.m3u8/xxx" format="HLS"/> 
     </media> 
     </media_list> 
    </asset> 
</asset_detail> 
+0

+1使用AVT更简洁。 – Cumbayah 2013-02-23 21:29:11

1

Yo你非常接近。传递给样式表的全局参数应该在外层声明(移动到output元素的后续兄弟节点)。 HLS格式匹配也可以直接在模板[@format='HLS']中完成。您还错过了value-of上的一个结束元素标记。最后,你不能直接改变匹配元素的属性;因此copy下面元件中,发光与现有属性+更新格式的匹配元素:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:param name="someVariable"/> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="media/version[@format='HLS']"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*"/> 
      <xsl:attribute name="rel_path"> 
       <xsl:value-of select="concat(@format,$someVariable)"/> 
      </xsl:attribute> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

希望这有助于。