Давайте начнем с вашего исходного XML.Как вы писали, что может быть несколько fig
узлов, они должны быть встроены в один единственный корневой элемент, я назвал его root
.
ДругойТребование заключается в том, что каждое используемое пространство имен должно быть где-то объявлено, например, в корневом элементе.
Таким образом, исходный XML, включая для простоты один (ваш) fig
элемент, может выглядеть следующим образом:
<root xmlns:xlink="urn:xlink">
<fig id="vid1" position="float" fig-type="video">
<label>Video 1</label>
<caption><p>Test video 1</p></caption>
<media xlink:href="test1.mp4" id="test1" mime-subtype="mp4" content-type="play-in-place"/>
</fig>
</root>
А теперь перейдем к сценарию XSLT.
Прежде всего вам необходимо повторить в открывающем теге stylesheet
каждое используемое пространство имен, например: xmlns:xlink="urn:xlink"
.
Для определения шаблонного текста вы можете использовать элементы xsl:param
, определяя их имена и значения, например:
<xsl:param name="role" select="'external-host-filename'"/>
<xsl:param name="Object1" select="'Video Player'"/>
Затем вы должны написать шаблон, соответствующий fig
, генерируя элемент media
с надлежащими атрибутамии содержание.Например, для создания атрибута id
вы можете написать:
<xsl:attribute name="id" select="@id"/>
Иногда атрибут можно скопировать из источника, например,
<xsl:copy-of select="media/@content-type"/>
А теперь часть изобретения: как ваш выводдолжен содержать два object-id
элементов, давайте напишем один шаблон, чтобы сгенерировать его с необходимыми формальными параметрами:
<xsl:template name="object">
<xsl:param name="pub-type"/>
<xsl:param name="content-type" required="no"/>
<xsl:param name="content"/>
<object-id>
<xsl:attribute name="pub-id-type" select="$pub-type"/>
<xsl:if test="$content-type != ''">
<xsl:attribute name="content-type" select="$content-type"/>
</xsl:if>
<xsl:value-of select="$content"/>
</object-id>
</xsl:template>
и вызвать его дважды, с надлежащими фактическими параметрами (см. ниже).
Последняя часть этого шаблона - скопировать два исходных элемента в вывод, используя copy-of
.Чтобы сделать скрипт короче, я написал его в одном выражении copy-of
.
И не забывайте о шаблоне идентификации .
Так что весь сценарий можетвыглядеть следующим образом:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xlink="urn:xlink">
<xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:param name="role" select="'external-host-filename'"/>
<xsl:param name="Object1" select="'Video Player'"/>
<xsl:template match="fig">
<media>
<xsl:attribute name="id" select="@id"/>
<xsl:attribute name="xlink:href" select="media/@xlink:href"/>
<xsl:attribute name="xlink:role" select="$role"/>
<xsl:copy-of select="media/@content-type"/>
<xsl:call-template name="object">
<xsl:with-param name="pub-type" select="'media-player-id'"/>
<xsl:with-param name="content" select="$Object1"/>
</xsl:call-template>
<xsl:call-template name="object">
<xsl:with-param name="pub-type" select="'other'"/>
<xsl:with-param name="content-type" select="'media-stream-id'"/>
<xsl:with-param name="content" select="'test 1'"/>
</xsl:call-template>
<xsl:copy-of select="label, caption"/>
</media>
</xsl:template>
<xsl:template name="object">
<xsl:param name="pub-type"/>
<xsl:param name="content-type" required="no"/>
<xsl:param name="content"/>
<object-id>
<xsl:attribute name="pub-id-type" select="$pub-type"/>
<xsl:if test="$content-type != ''">
<xsl:attribute name="content-type" select="$content-type"/>
</xsl:if>
<xsl:value-of select="$content"/>
</object-id>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>
</xsl:stylesheet>
Рабочий пример см. http://xsltransform.net/nb9MWtn