2015-08-07 2 views
1

Мне нужно отключить (или разложить) некоторые элементы, которые в настоящее время завернуты в теги абзаца (например, теги <p>). Но их не должно быть, и мне нужно иметь возможность исправить это, используя XSLT.Развертывание элементов с помощью XSLT

Это может выглядеть, например:

<paragraph>Some text here with a <bold>word</bold> in bold, for example, and then an image: 
    <image href="whatever.png"></image> 
    and possibly some more text here. 
</paragraph> 

Здесь мне нужно выделить текст (включая строковый тэг) в качестве одного пункта, а затем изображений отдельно, а не внутри абзаца, а затем следует новый абзац для текста в конце. Например:

<paragraph>Some text here with a <bold>word</bold> in bold, for example, and then an image:</paragraph> 
    <image href="whatever.png"></image> 
<paragraph>and possibly some more text here.</paragraph> 

Но я не могу понять, как это сделать. Я могу сделать это для каждого узла, но тогда жирный тег будет также помещен в отдельный абзац, и я не хочу этого.

Обратите внимание, что тег является всего лишь примером. Такая же ситуация будет происходить со списками, таблицами и т. Д. И в основном проблема заключается в том, что они были завернуты в теги абзацев, когда их не должно было быть. Поэтому текст (включая встроенные элементы, такие как жирный шрифт, курсив и т. Д.) Должен быть сохранен как параграфы в одном фрагменте, но другие типы элементов, изображений, таблиц и т. Д. Должны быть обернуты из него, сохраняя при этом правильные порядок содержания курса.

Любые идеи оценены!

+2

Элементы 'image',' list', 'table' всегда направляют детей o f элементы 'paragraph'? Или может быть дополнительная вложенность, например '. Это текст bold . '? Какую версию XSLT вы используете или можете использовать? –

ответ

2

Предполагая XSLT 3.0 вы можете сделать

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="3.0" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs"> 

<xsl:template match="@* | node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@* , node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="paragraph"> 
    <xsl:for-each-group select="node()" group-adjacent="boolean(self::image | self::table | self::list)"> 
    <xsl:choose> 
     <xsl:when test="current-grouping-key()"> 
     <xsl:apply-templates select="current-group()"/> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:copy select=".."> 
      <xsl:apply-templates select="current-group()"/> 
     </xsl:copy> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:for-each-group> 
</xsl:template> 

</xsl:stylesheet> 

с XSLT 2.0 вы можете изменить шаблон для paragraph в

<xsl:template match="paragraph"> 
    <xsl:for-each-group select="node()" group-adjacent="boolean(self::image | self::table | self::list)"> 
    <xsl:choose> 
     <xsl:when test="current-grouping-key()"> 
     <xsl:apply-templates select="current-group()"/> 
     </xsl:when> 
     <xsl:otherwise> 
     <paragraph> 
      <xsl:apply-templates select="current-group()"/> 
     </paragraph> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:for-each-group> 
</xsl:template> 

С XSLT 1.0 Ниже приведен пример использования Sibling рекурсию, чтобы попытаться решаем, что:

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 

<xsl:template match="@* | node()" name="identity"> 
    <xsl:copy> 
    <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="paragraph"> 
    <xsl:apply-templates select="node()[1]"/> 
</xsl:template> 

<xsl:template match="paragraph/image | paragraph/table | paragraph/list"> 
    <xsl:call-template name="identity"/> 
    <xsl:apply-templates select="following-sibling::node()[1]"/> 
</xsl:template> 

<xsl:template match="paragraph/node()[not(self::image | self::table | self::list)]"> 
    <paragraph> 
    <xsl:call-template name="identity"/> 
    <xsl:apply-templates select="following-sibling::node()[1][not(self::image | self::table | self::list)]" mode="copy"/> 
    </paragraph> 
    <xsl:apply-templates select="following-sibling::node()[self::image | self::table | self::list][1]"/> 
</xsl:template> 

<xsl:template match="paragraph/node()[not(self::image | self::table | self::list)]" mode="copy"> 
    <xsl:call-template name="identity"/> 
    <xsl:apply-templates select="following-sibling::node()[1][not(self::image | self::table | self::list)]" mode="copy"/> 
</xsl:template> 

</xsl:stylesheet> 
+0

Отличный ответ, спасибо! Он работает при тестировании с XSLT 2.0 и Saxon. Проблема только в том, что в этом случае мне, вероятно, придется использовать XSLT 1.0, я забыл это сказать. Есть ли вероятность наличия эквивалента для 1.0? – Anders

+0

@AndersSvensson, я добавил образец XSLT 1.0, который выполняет рекурсию sibling (он начинается с 'paragraph/node() [1]', а затем проходит следующую ось-брата для сбора узлов, принадлежащих вместе, и для прямого вывода 'image', элементы 'table' и' list'). –

+0

Спасибо, он отлично работает! – Anders

Смежные вопросы