Двигатель Safari XSLT теряет пространство имен по атрибутам

У меня есть XSLT, который соответствует определенным атрибутам и помещает их в другое пространство имен. Вот упрощенная версия:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="urn:test:ns1"
    xmlns:ns2="urn:test:ns2">
    <xsl:output method="xml" indent="no" encoding="UTF-8"/>

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

    <xsl:template match="@*[starts-with(local-name(), 'test-')]">
        <xsl:attribute name="ns2:{substring-after(local-name(), '-')}" namespace="urn:test:ns2">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

Вот пример ввода:

<?xml version="1.0" encoding="UTF-8" ?>
<hello-world
    xmlns="urn:test:ns1"
    xmlns:ns3="urn:test:ns3"
    rootAttr="stays in implicit namespace"
    ns3:passMe="stays in the ns3 namespace"
    test-someRootAttr="goes into the ns2 namespace, pulls up ns declaration">
    <test
        defaultAttr="stays in implicit namespace"
        test-someAttr="goes into the ns2 namespace"
        ns3:namedAttr="stays in the ns3 namespace">
        Something
    </test>
    <ns3:cat
        defaultAttr="stays in the implicit namespace"
        test-catName="goes into the ns2 namespace"
        ns3:namedAttr="stays in the ns3 namespace">
        a cat
    </ns3:cat>
</hello-world>

И вот ожидаемый результат:

<?xml version="1.0" encoding="UTF-8" ?>
<hello-world
    xmlns="urn:test:ns1"
    xmlns:ns2="urn:test:ns2"
    xmlns:ns3="urn:test:ns3"
    rootAttr="stays in implicit namespace"
    ns3:passMe="stays in the ns3 namespace"
    ns2:someRootAttr="goes into the ns2 namespace, pulls up ns declaration">
    <test
        defaultAttr="stays in implicit namespace"
        ns2:someAttr="goes into the ns2 namespace"
        ns3:namedAttr="stays in the ns3 namespace">
        Something
    </test>
    <ns3:cat
        defaultAttr="stays in the implicit namespace"
        ns2:catName="goes into the ns2 namespace"
        ns3:namedAttr="stays in the ns3 namespace">
        a cat
    </ns3:cat>
</hello-world>

Это отлично работает на Chrome, Firefox, IE 9+ и Android. Однако в Safari я получаю следующий вывод:

<?xml version="1.0" encoding="UTF-8" ?>
<hello-world
    xmlns="urn:test:ns1"
    xmlns:ns3="urn:test:ns3"
    xmlns:ns2="urn:test:ns2"
    rootAttr="stays in implicit namespace"
    passMe="stays in the ns3 namespace"
    someRootAttr="goes into the ns2 namespace, pulls up ns declaration">
    <test
        defaultAttr="stays in implicit namespace" 
        someAttr="goes into the ns2 namespace" 
        namedAttr="stays in the ns3 namespace">
        Something
    </test>
    <ns3:cat
        defaultAttr="stays in the implicit namespace" 
        catName="goes into the ns2 namespace" 
        namedAttr="stays in the ns3 namespace">
        a cat
    </ns3:cat>
</hello-world>

Обратите внимание, что объявления пространства имен верны, но в атрибутах отсутствует желаемый префикс пространства имен.

Весь этот код находится в проекте github, который построен TravisCI и использует Sauce Labs для тестирования на разных комбинациях браузера/ОС.

Могу ли я сделать что-то по-другому с моим XSLT, что было бы более правильным способом выполнить это, что могло бы работать на всех двигателях? Или это просто ошибка в Safari? Любые идеи для обходных путей были бы высоко оценены.

Ответ 1

Без каких-либо доказательств обратного, это, похоже, ошибка в Safari. Я сообщил об этом Apple (rdar://23207226), но до сих пор ничего не слышал от них.

Единственным доступным обходным решением является запуск XSLT на каком-то другом движке (на стороне сервера или, возможно, на стороннем javascript-движке).

Ответ 2

Я думаю, что это ошибка. Как работа вокруг вы можете попытаться установить пространство имен, которое вы хотите, а также на xsl:attribute namespace="urn:test:ns2".