Как легко конвертировать xml в другой формат, используя XSLT - PullRequest
0 голосов
/ 25 мая 2018

В настоящее время пытаюсь научить себя основному XSLT в практической среде - задаюсь вопросом, как проще всего это преобразовать:

<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>

В этот формат вместе с добавлением стандартного текста (external-host-filename, Videoигрок), который должен выводиться при каждом преобразовании.

<media id="vid1" xlink:href="test1.mp4" xlink:role="external-host-filename" content-type="play-in-place">
<object-id pub-id-type="media-player-id">Video Player</object-id>
<object-id pub-id-type="other" content-type="media-stream-id">test 1</object-id>
<label>Video 1</label>
<caption><p>Test video 1</p></caption>
</media>

Любой ввод был бы великолепен, спасибо!

1 Ответ

0 голосов
/ 25 мая 2018

Давайте начнем с вашего исходного 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...