XSL-преобразование дает разные результаты, когда меняются две одинаковые строки - PullRequest
4 голосов
/ 27 декабря 2011

Я пытаюсь объединить файл 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 Ответ

2 голосов
/ 27 декабря 2011

Но, когда я пытаюсь изменить порядок 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:g копируется из одного из документов SVG, затем только атрибуты верхнего элемента и всего оставшегося документа 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 для этого элемента. Размещение его после копирования других элементов приводит к размещению этих атрибутов на последнем скопированном элементе, а не на первоначальном владельце атрибутов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...