Как написать XSL, используя пространство имен по умолчанию?

Скажем, у меня есть файл XML, который выглядит так:

<?xml version="1.0" encoding="UTF-8"?>

<Project xmlns="http://My/Project.xsd">
    <Thing Name="test"/>
</Project>

И мой XSLT:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes" xmlns="http://My/Project.xsd">
    <xsl:output method="text" version="1.0" encoding="UTF-8" indent="no"/>

    <xsl:template match="Thing">
        <xsl:value-of select="@Name"/>
    </xsl:template>
</xsl:stylesheet>

Результатом является [NewLine][Tab][NewLine], который соответствует интервалу XML-файла.

Если я изменю свой XSLT на: (добавлен префикс)

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes" xmlns:N="http://My/Project.xsd">
    <xsl:output method="text" version="1.0" encoding="UTF-8" indent="no"/>

    <xsl:template match="N:Thing">
        <xsl:value-of select="@Name"/>
    </xsl:template>
</xsl:stylesheet>

Результатом является [NewLine][Tab]test[NewLine], который снова соответствует интервалу XML-файла, но включает значение атрибута «Имя».

Мой ожидаемый результат просто test. Никаких новых строк, никаких вкладок — он вообще не должен соответствовать формату XML-файла.

Я хочу написать XML и XSLT без использования префиксов. Как я могу сделать этот вывод тем, что я ожидаю?


person Josh M.    schedule 01.04.2011    source источник


Ответы (1)


Здесь есть две проблемы: во-первых, вы не хотите указывать префикс пространства имен, а во-вторых, вы не хотите, чтобы пробелы из исходного документа влияли на ваш вывод. Давайте обсудим их отдельно.

Использование префикса пространства имен: краткий ответ — нет — вы не можете написать шаблон XSL, который соответствует элементам в определенном пространстве имен, не указывая такое пространство имен с помощью префикса. В своем первом XSLT вы можете прочитать определение шаблона, например: "Я хочу выбрать узел с именем Вещь, у которого нет пространства имен", в то время как на самом деле вы хотите сказать "Я хочу выбрать узел с именем Thing, который имеет пространство имен http://My/Project.xsd< /а>". Так работает спецификация XPath 1.0 (подробнее см. в этом статью).

Избавьтесь от пробелов. Используйте инструкцию <xsl:strip-space elements="*"/> в начале таблицы стилей, чтобы указать, что вы не хотите, чтобы пробелы из всех исходных элементов сохранялись в выходном документе. Если вы хотите сохранить некоторые из них, используйте также <xsl:preserve-spaces elements="myNode">.

person oiavorskyi    schedule 01.04.2011
comment
Чтобы добавить к этому, причина, по которой вы получаете пробел, заключается в том, что в вашей таблице стилей есть встроенные правила шаблона, которые обрабатывают узлы, которые вы явно не сопоставляете. Правило по умолчанию для текстового узла — даже текстового узла, состоящего только из пробелов — состоит в том, чтобы скопировать его в вывод. Как и xsl:strip-space, еще один способ предотвратить это — добавить правило <xsl:template match=text()"/>, правила пустого шаблона, означающие, что когда процессор сталкивается с текстовым узлом, он по умолчанию игнорирует его. - person Michael Kay; 01.04.2011
comment
Михаил, отличный комментарий! И спасибо за книгу, кстати :) - person oiavorskyi; 01.04.2011
comment
Еще одно дополнение: вы можете выбирать элементы без учета пространства имен с помощью *[local-name()='whatever'] в XSLT/XPath 1.0 или *:whatever в XSLT/XPath 2.0. - person ; 01.04.2011