使用xsl将常量值替换为xml属性值

时间:2014-12-22 12:15:23

标签: xslt xpath svg xslt-1.0

有XML节点

<svg>
    <g transform="translate(113.63-359.13)">
        <use fill="#f00" xlink:href="#D"/>
        <g transform="translate(72.59-8.504)">
            <use xlink:href="#E"/>
            <path fill="#f00" stroke="#000" stroke-linejoin="round" stroke-linecap="round" stroke-width=".24" d="m6.04 526.26h19.843v4.961h-19.843z"/>
            <use xlink:href="#F"/>
        </g>
        <text x="20.41" y="527.6" fill="#000" font-family="Arial" font-size="8">ProcessOutbound</text>
    </g>
</svg>

可以通过此Xpath找到

/svg/g[text="ProcessOutbound"]/use

这也很好

/svg/g[text="ProcessOutbound"]/use/@fill

但由于某些原因,xsl没有用#00f替换#f00这是累了

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
    <xsl:param name="blue" select="'#00f'"/>

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

    <xsl:template match='/svg/g[text="ProcessOutbound"]/use'>
        <xsl:attribute name='fill'>
            <xsl:value-of select="'$blue'"/>
        </xsl:attribute>
    </xsl:template>

</xsl:stylesheet>

实际上整个svg文件被复制但是fill属性没有被替换。我尝试使用替换的填充值来获得副本

使用xsl?

将常量值替换为attribut值的正确方法是什么?

所以预期的结果应该是

   <g transform="translate(113.63-359.13)">
    <use fill="#00f" xlink:href="#D"/>
    <g transform="translate(72.59-8.504)">
        <use xlink:href="#E"/>
        <path fill="#f00" stroke="#000" stroke-linejoin="round" stroke-linecap="round" stroke-width=".24" d="m6.04 526.26h19.843v4.961h-19.843z"/>
        <use xlink:href="#F"/>
    </g>
    <text x="20.41" y="527.6" fill="#000" font-family="Arial" font-size="8">ProcessOutbound</text>
</g>

4 个答案:

答案 0 :(得分:1)

您的XSLT有一些不正确之处:

  • 尝试用属性替换整个'use'元素。
  • 您在$blue周围使用两对引号,这会使其被视为字符串。
  • 即使您的XML使用命名空间,也没有使用命名空间。

请试试这个:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:svg="http://www.w3.org/2000/svg">
    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
    <xsl:param name="blue" select="'#00f'"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

  <xsl:template match='svg:g[svg:text = "ProcessOutbound"]/svg:use/@fill'>
        <xsl:attribute name='fill'>
            <xsl:value-of select="$blue"/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

在样本输入上运行时,结果为:

<svg xmlns:xlink="...">
    <g transform="translate(113.63-359.13)">
        <use xlink:href="#D" fill="#00f" />
        <g transform="translate(72.59-8.504)">
            <use xlink:href="#E" xmlns:xlink="x" />
            <path fill="#f00" d="m6.04 526.26h19.843v4.961h-19.843z" stroke-width=".24" stroke-linecap="round" stroke-linejoin="round" stroke="#000" />
            <use xlink:href="#F" />
        </g>
        <text font-family="Arial" fill="#000" font-size="8" y="527.6" x="20.41">ProcessOutbound</text>
    </g>
</svg>

http://www.xsltcake.com/slices/d8pdoi

答案 1 :(得分:1)

假设格式正确的输入(前缀xlink:未绑定,因为您没有包含其命名空间定义),请使用下面的样式表。

不是匹配元素use,而是直接匹配您要修改的节点fill的{​​{1}}属性。

<强>样式表

如果我理解正确的话,您的问题表明第二个模板应该与use实际匹配。

/svg/g[8]/use/@fill

XML输出

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

<xsl:param name="blue" select="'#00f'"/>

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

    <xsl:template match="/svg/g/use/@fill">
        <xsl:attribute name="fill">
            <xsl:value-of select="$blue"/>
        </xsl:attribute>
    </xsl:template>

</xsl:stylesheet>

编辑:如评论中所述,如果您的SVG元素实际位于命名空间中,请尝试以下样式表:

<强>样式表

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns:xlink="http://www.w3.org/1999/xlink">
   <g transform="translate(113.63-359.13)">
      <use fill="#00f" xlink:href="#D"/>
      <g transform="translate(72.59-8.504)">
         <use xlink:href="#E"/>
         <path fill="#f00" stroke="#000" stroke-linejoin="round" stroke-linecap="round" stroke-width=".24" d="m6.04 526.26h19.843v4.961h-19.843z"/>
         <use xlink:href="#F"/>
      </g>
      <text x="20.41" y="527.6" fill="#000" font-family="Arial" font-size="8">ProcessOutbound</text>
   </g>
</svg>

答案 2 :(得分:1)

如果我正确猜测并且您的输入是有效的SVG文档,则其所有元素都位于 SVG名称空间中。 IOW,您的输入示例应该看起来像这样:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <g transform="translate(113.63-359.13)">
        <use fill="#f00" xlink:href="#D"/>
        <g transform="translate(72.59-8.504)">
            <use xlink:href="#E"/>
            <path fill="#f00" stroke="#000" stroke-linejoin="round" stroke-linecap="round" stroke-width=".24" d="m6.04 526.26h19.843v4.961h-19.843z"/>
            <use xlink:href="#F"/>
        </g>
        <text x="20.41" y="527.6" fill="#000" font-family="Arial" font-size="8">ProcessOutbound</text>
    </g>
</svg>

然后你的 XSLT

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:param name="blue" select="'#00f'"/>

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

<xsl:template match="svg:g[svg:text='ProcessOutbound']/svg:use/@fill">
    <xsl:attribute name='fill'>
        <xsl:value-of select="$blue"/>
    </xsl:attribute>
</xsl:template>

</xsl:stylesheet>

答案 3 :(得分:0)

试试这个,

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:param name="blue" select="'#00f'"/>

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

<xsl:template match="/svg/g[contains(text, 'ProcessOutbound')]/use">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
    <xsl:attribute name='fill'>
        <xsl:value-of select="$blue"/>
    </xsl:attribute>
    <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

如果这不符合您的要求,请提供您所需的简单文字。