XSLT 条件模板匹配两个属性

XSLT conditional template match on two attributes

我必须解析这个 SVG 并应用一些转换:

<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="540pt" height="263pt" viewBox="0 0 540 263" version="1.1">
    <g id="surface1">
        ...
        <path style=" stroke:black;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 270 67.160156 L 270.238281 67.640625 L 277.679688 67.640625 "/>
        <path style=" stroke:black;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 270.238281 67.640625 L 271.199219 68.839844 L 285.359375 68.839844 "/>
        <path style=" stroke:black;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 270.238281 67.640625 L 277.679688 67.640625 L 285.359375 68.839844 "/>
        <path style=" stroke:black;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 271.199219 68.839844 L 272.878906 71.238281 L 293.039062 71.238281 "/>
        <path style=" stroke:black;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 271.199219 68.839844 L 285.359375 68.839844 L 293.039062 71.238281 "/>
        <path style=" stroke:black;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 272.878906 71.238281 L 275.28125 74.601562 L 300 74.601562 "/>
        ...
    </g>
</svg>

我需要一个匹配 path 元素的模板,其中 style 属性包含字符串 fill:rgb(0%,0%,0%)d 属性包含两倍的字母 [=21] =].这是我得到的:

<xsl:template match="@style[contains(., 'fill:rgb(0%,0%,0%)')] and @d[string-length() - string-length(translate(., 'L', '')) = 2]">
    <xsl:attribute name="d">
        <xsl:value-of select="."/>
        <xsl:text>Z</xsl:text>
    </xsl:attribute>
</xsl:template>

似乎每个条件都单独起作用,但当在一起时,它就不起作用了。

<xsl:template match="@style[contains(., 'fill:rgb(0%,0%,0%)')]">
    <xsl:attribute name="d">
        <xsl:value-of select="."/>
        <xsl:text>Z</xsl:text>
    </xsl:attribute>
</xsl:template>

<xsl:template match="@d[string-length() - string-length(translate(., 'L', '')) = 2]">
    <xsl:attribute name="d">
        <xsl:value-of select="."/>
        <xsl:text>Z</xsl:text>
    </xsl:attribute>
</xsl:template>

此外,path 元素的匹配似乎不起作用...

<xsl:template match="path">
    <xsl:attribute name="d">
        <xsl:value-of select="."/>
        <xsl:text>Z</xsl:text>
    </xsl:attribute>
</xsl:template>

这是完整的转换文件。问题似乎是 path 元素的匹配。

<?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"/>

    <xsl:param name="stroke">black</xsl:param>
    <xsl:param name="stroke-width">50px</xsl:param>

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

    <xsl:template match="path[@style[contains(., 'fill:rgb(0%,0%,0%)')] and @d[string-length() - string-length(translate(., 'L', '')) = 2]]">
        <xsl:attribute name="d">
            <xsl:value-of select="."/>
            <xsl:text>Z</xsl:text>
        </xsl:attribute>
    </xsl:template>

    <xsl:template match="@*|text()">
        <xsl:copy/>
    </xsl:template>

</xsl:stylesheet>

预期结果应该是(注意附加到 d 属性的字母 Z):

<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="540pt" height="263pt" viewBox="0 0 540 263" version="1.1">
    <g id="surface1">
        ...
        <path style=" stroke:black;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 270 67.160156 L 270.238281 67.640625 L 277.679688 67.640625 Z"/>
        <path style=" stroke:black;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 270.238281 67.640625 L 271.199219 68.839844 L 285.359375 68.839844 Z"/>
        <path style=" stroke:black;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 270.238281 67.640625 L 277.679688 67.640625 L 285.359375 68.839844 Z"/>
        <path style=" stroke:black;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 271.199219 68.839844 L 272.878906 71.238281 L 293.039062 71.238281 Z"/>
        <path style=" stroke:black;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 271.199219 68.839844 L 285.359375 68.839844 L 293.039062 71.238281 Z"/>
        <path style=" stroke:black;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 272.878906 71.238281 L 275.28125 74.601562 L 300 74.601562 Z"/>
        ...
    </g>
</svg>

您遇到的第一个问题是名称空间。 XML 输入中的元素是命名空间

的一部分
<svg xmlns="http://www.w3.org/2000/svg"

这意味着您也需要在 XSLT 中引用该命名空间....

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

然后你在模板匹配中使用这个前缀

<xsl:template match="svg:path">

现在,您实际上想要在此处匹配 d 属性,因此您的模板将如下所示

<xsl:template match="svg:path[contains(@style, 'fill:rgb(0%,0%,0%)')]
     /@d[string-length() - string-length(translate(., 'L', '')) = 2]">
    <xsl:attribute name="d">
        <xsl:value-of select="."/>
        <xsl:text>Z</xsl:text>
    </xsl:attribute>
</xsl:template>

All I want to achieve, is to add the letter Z to the d attribute of the paths that fit both conditions.

那么你的模板应该匹配 @d 属性或其父元素 path - 而不是它的兄弟 @style 属性,就像你现在拥有的那样(更不用说你的语法无效)。

这样试试,也许:

<xsl:template match="@d[string-length() - string-length(translate(., 'L', '')) = 2] [contains(../@style, 'fill:rgb(0%,0%,0%)')]">
    <xsl:attribute name="d">
        <xsl:value-of select="."/>
        <xsl:text>Z</xsl:text>
    </xsl:attribute>
</xsl:template>