当交换两条相同的行时,XSL转换会产生不同的结果

时间:2011-12-27 13:07:48

标签: java xslt svg

我正在尝试合并到svg文件中。我有两个文件,“bg.svg”:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
        xmlns="http://www.w3.org/2000/svg"
        version="1.1"
        width="500"
        height="500"
        xml:space="preserve">

    <g>
        <circle cy="250px" cx="250px" r="200" style="fill:black"></circle>
        <circle cy="250px" cx="250px" r="195" style="fill:white"></circle>
    </g>
</svg>

和“arrow.svg”:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
        xmlns="http://www.w3.org/2000/svg"
        version="1.1"
        width="500"
        height="500"
        id="arrow"
        xml:space="preserve">
    <g id="g10">
        <path d="M 250 245 L 250 255 L 400 255 L 400 265 L 415 250 L 400 235 L 400 245 L 250 245 " style="fill:red;stroke:#500;"></path>
    </g>
</svg>.

然后,我试图将它与以下XSL模板合并:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:svg="http://www.w3.org/2000/svg">


    <xsl:variable name="bg-doc" select="document('bg.svg')"/>

    <xsl:template match="/svg:svg">
        <xsl:copy>
            <xsl:apply-templates select="./@*|./node()" />
            <xsl:apply-templates select="$bg-doc/svg:svg/svg:g" />
        </xsl:copy>
    </xsl:template>

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


</xsl:stylesheet>

......通过这个Java代码:

TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer( new StreamSource( new File("merge.xsl" ) ) );
transformer.transform( new StreamSource( new File("arrow.svg") ),
                           new StreamResult( new File("out.svg") ) );

这种转变有正确的结果:

<?xml version = '1.0' encoding = 'UTF-8'?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500" height="500" id="arrow" xml:space="preserve">
    <g id="g10">
        <path d="M 250 245 L 250 255 L 400 255 L 400 265 L 415 250 L 400 235 L 400 245 L 250 245 "
              style="fill:red;stroke:#500;"/>
    </g>
    <g>
        <circle cy="250px" cx="250px" r="200" style="fill:black"/>
        <circle cy="250px" cx="250px" r="195" style="fill:white"/>
    </g>
</svg>

但是,当我尝试更改11行和12行XSL模板的顺序时:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:svg="http://www.w3.org/2000/svg">


    <xsl:variable name="bg-doc" select="document('bg.svg')"/>

    <xsl:template match="/svg:svg">
        <xsl:copy>
            <xsl:apply-templates select="$bg-doc/svg:svg/svg:g" />
            <xsl:apply-templates select="./@*|./node()" />
        </xsl:copy>
    </xsl:template>

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


</xsl:stylesheet>

...转换返回奇怪的(无效的)XML:

<?xml version = '1.0' encoding = 'UTF-8'?>
<svg xmlns="http://www.w3.org/2000/svg">
    <g>
        <circle cy="250px" cx="250px" r="200" style="fill:black"/>
        <circle cy="250px" cx="250px" r="195" style="fill:white"/>
    </g>
    <svg version="1.1" width="500" height="500" id="arrow" xml:space="preserve">
        <g id="g10">
            <path d="M 250 245 L 250 255 L 400 255 L 400 265 L 415 250 L 400 235 L 400 245 L 250 245 "
                  style="fill:red;stroke:#500;"/>
        </g>
    </svg>

任何想法为什么会发生?

1 个答案:

答案 0 :(得分:2)

  

但是,当我试图改变11和12行XSL的顺序时   模板:

<xsl:template match="/svg:svg"> 
    <xsl:copy> 
        <xsl:apply-templates select="$bg-doc/svg:svg/svg:g" /> 
        <xsl:apply-templates select="./@*|./node()" /> 
    </xsl:copy> 
</xsl:template>
     

转换返回奇怪的(无效的)XML

这正是您通过交换两行代码指定的内容:首先从一个SVG文档中复制svg:g元素,然后只查看顶部元素的属性和剩余的整个元素复制SVG文档。

解决方案

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

    <xsl:variable name="bg-doc" select=
    "document('file:///c:/temp/delete/bg.svg')"/>

    <xsl:template match="/svg:svg">
        <xsl:copy>
            <xsl:apply-templates select="@*" />
            <xsl:apply-templates select="$bg-doc/svg:svg/svg:g" />
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>

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

对提供的XML文档应用此转换时arrow.svg):

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
        xmlns="http://www.w3.org/2000/svg"
        version="1.1"
        width="500"
        height="500"
        id="arrow"
        xml:space="preserve">
    <g id="g10">
        <path d="M 250 245 L 250 255 L 400 255 L 400 265 L 415 250 L 400 235 L 400 245 L 250 245 " style="fill:red;stroke:#500;"></path>
    </g>
</svg>

以及bg.svg处提供的第二个文档c:\temp\delete\):

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
        xmlns="http://www.w3.org/2000/svg"
        version="1.1"
        width="500"
        height="500"
        xml:space="preserve">

    <g>
        <circle cy="250px" cx="250px" r="200" style="fill:black"></circle>
        <circle cy="250px" cx="250px" r="195" style="fill:white"></circle>
    </g>
</svg>

现在生成了正确的结果

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500" height="500" id="arrow" xml:space="preserve"><g>
        <circle cy="250px" cx="250px" r="200" style="fill:black"/>
        <circle cy="250px" cx="250px" r="195" style="fill:white"/>
    </g>
    <g id="g10">
        <path d="M 250 245 L 250 255 L 400 255 L 400 265 L 415 250 L 400 235 L 400 245 L 250 245 " style="fill:red;stroke:#500;"/>
    </g>
</svg>

解释:复制元素的属性必须紧跟此元素的xsl:copy指令。复制其他元素后放置它会导致将这些属性放在最后复制的元素上,而不是放在属性的原始所有者上。