XMLStarlet + XInclude + XSLT

Я хотел бы включить содержимое XML-документа в другой XML-документ и преобразовать его с помощью xmlstarlet+XSLT. Я пытаюсь использовать XInclude. (Я новичок как в XInclude, так и в XSLT.) Однако xmlstarlet не будет обрабатывать включенный XML-документ, он просто оставляет нетронутым узел включения.

Файл a.xml:

<?xml version="1.0" ?>
<doc xmlns:xi="http://www.w3.org/2001/XInclude">
a
<xi:include href="b.xml" />
b
</doc>

Файл b.xml:

<?xml version="1.0" ?>
<snippet>
c
</snippet>

Шаблон x.xsl "сквозной":

<?xml version="1.0" encoding="windows-1250" ?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" />

<xsl:template match="/">
<xsl:copy-of select="."/>
</xsl:template>

</xsl:transform>

Командная строка для запуска:

xmlstarlet tr x.xsl a.xml

И ожидаемый результат будет примерно таким:

<?xml version="1.0" ?>
<doc xmlns:xi="http://www.w3.org/2001/XInclude">
a
<snippet>
c
</snippet>
b
</doc>

Тем не менее, результат, который я получаю:

<?xml version="1.0"?>
<doc xmlns:xi="http://www.w3.org/2001/XInclude">
a
<xi:include href="b.xml"/>
b
</doc>

Теперь, что я делаю неправильно?


person peter.hrasko.sk    schedule 27.03.2015    source источник
comment
Проверьте параметры, перечисленные xmlstarlet tr --help   -  person npostavs    schedule 27.03.2015
comment
Я так и сделал, и действительно нашел параметр --xinclude. Но, как я вижу из ответа М.М., я не использовал его должным образом. Почему я написал --xinclude=b.xml теперь выше моего понимания.   -  person peter.hrasko.sk    schedule 27.03.2015


Ответы (1)


Как уже было сказано npostavs, xmlstarlet по умолчанию не включает документы XInclude, вам нужно явно указать это как --xinclude. Тогда результат тот, который вы ожидали:

$ xml tr --xinclude x.xsl a.xml
<?xml version="1.0"?>
<doc xmlns:xi="http://www.w3.org/2001/XInclude">
a
<snippet>
c
</snippet>
b
</doc>

За исключением объявления пространства имен xi:, которое невозможно устранить с помощью XSLT 1.0 и простого <xsl:copy-of select="."/>. Если это проблема, таблица стилей становится немного сложнее, так как copy-namespaces="no" недоступен в XSLT 1.0:

<?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:template match="/">
<xsl:apply-templates select="." mode="copy-no-namespaces"/>
</xsl:template>

<xsl:template match="*" mode="copy-no-namespaces">
    <xsl:element name="{local-name()}" namespace="{namespace-uri()}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates select="node()" mode="copy-no-namespaces"/>
    </xsl:element>
</xsl:template>

<xsl:template match="comment()| processing-instruction()" mode="copy-no-namespaces">
    <xsl:copy/>
</xsl:template>

</xsl:stylesheet>

Это стандартный подход к имитации copy-namespaces="no" в XSLT 1.0, описанный Майклом Кеем здесь. Тогда результат будет

$ xml tr --xinclude x.xsl a.xml
<?xml version="1.0"?>
<doc>
a
<snippet>
c
</snippet>
b
</doc>
person Mathias Müller    schedule 27.03.2015
comment
Спасибо. Проверю, как только доберусь до ПК. - person peter.hrasko.sk; 27.03.2015