2015-03-27 5 views
3

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

Файл 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> 

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

+1

Проверьте параметры, указанные на 'XMLStarlet тр --help' – npostavs

+0

я сделал, и на самом деле я нашел --xinclude параметр. Но, как я вижу из ответа М. М., я не использовал его должным образом. Почему я написал «-xinclude = b.xml», теперь я не понимаю. – nop77svk

ответ

3

Как уже было предложено 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, как описано here Майкл Кей. Тогда результат будет

$ xml tr --xinclude x.xsl a.xml 
<?xml version="1.0"?> 
<doc> 
a 
<snippet> 
c 
</snippet> 
b 
</doc> 
+0

Спасибо. Будет проверять его, как только я доберусь до ПК. – nop77svk