问题
there is that XML Node
<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>
which can be found by this Xpath
/svg/g[text="ProcessOutbound"]/use
also this work fine
/svg/g[text="ProcessOutbound"]/use/@fill
but for some reasons that xsl is not replaceing #f00 with #00f which is what have tired
<?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>
actually the whole svg file is copied but the fill attribute is not replaced. I tried to achive a copy but with the replaced fill value
What is the correct way to replace attribut values with constant values by xsl ?
So the expected result should look like
<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>
回答1:
There are a few things incorrect with your XSLT:
- It is trying to replace the whole 'use' element with an attribute.
- You are using two pairs of quotes around
$blue
, which causes it to be treated as a string. - You are not using namespaces even though your XML uses a namespace.
Please try this:
<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>
When run on your sample input, the result is:
<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
回答2:
If I am guessing correctly and your input is a valid SVG document, then all its elements are in the SVG namespace. IOW, your input example should actually look like this:
<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>
And then your 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:
Assuming a well-formed input (the prefix xlink:
is not bound because you did not include its namespace definition), use the stylesheet below.
Rather than matching the element use
, directly match the node you'd like to modify, the fill
attribute of use
.
Stylesheet
Your question suggests that the second template should actually match /svg/g[8]/use/@fill
if I understood correctly.
<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>
XML Output
<?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>
EDIT: As mentioned in a comment, try the following stylesheet if your SVG elements actually are in a namespace:
Stylesheet
<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" 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:svg/svg:g/svg:use/@fill">
<xsl:attribute name="fill">
<xsl:value-of select="$blue"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
回答4:
Try with this,
<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>
If this not meeting u r requirement, provide u r simple required text.
来源:https://stackoverflow.com/questions/27602542/replace-xml-attribute-values-with-constant-values-by-xsl