Получение значения элемента с помощью XSLT, затем его удаление

#xml #xslt

#xml #xslt

Вопрос:

Я использую XSLT для очистки некоторых XML, связанных с InDesign, для использования в других системах. Мне нужно иметь возможность извлекать значение из тегов, вложенных в текстовое тело, а затем удалять их.

В частности, заголовок и подпись встроены в текстовое тело. Мне нужно иметь возможность извлекать их и помещать в теги заголовка — я могу это сделать, но, похоже, я не могу извлечь их из тела, пока я этим занимаюсь.

Вот мой (упрощенный) XML:

 <?xml version="1.0" encoding="UTF-8"?>
<k4Export xmlns="http://www.vjoon.com/K4Export/1.4.2">  
    <publication>
        <id>107233722</id>
        <name>NGM</name>
        <origin>origin</origin>
        <issue>
            <article>
                <textObjects>
                    <textObject>
                        <text>
                            <inlineTag name="Story">
                                <inlineTag name="body">
                                    <inlineTag name="headline">The Headline</inlineTag> Lorem ipsum dolor sit amet, 
                                    consectetur adipiscing elit. <em>Vivamus mollis</em> ligula quis mi
                                     blandit interdum. In rutrum imperdiet suscipit. Fusce interdum, 
                                    sem id scelerisque molestie, purus ligula fringilla sapien, nec
                                     auctor velit eros eget felis. Duis eu tellus purus. Donec id viverra
                                     neque.</inlineTag>

                                    <inlineTag name="body">Donec nec nulla neque, sit amet placerat 
                                        elit. Nulla pulvinar elit sapien. Donec venenatis, arcu sed
                                         pellentesque ultrices, neque mi sollicitudin elit, nec fermentum
                                         eros nibh aliquam leo. Nam lectus neque, dapibus in scelerisque
                                         in, fermentum nec ipsum.</inlineTag>

                                    <inlineTag name="body">Sed sed <strong>congue</strong> neque. Nulla
                                     nec ipsum vitae lacus consectetur convallis sed et nulla. Integer
                                     posuere viverra felis, at pulvinar risus scelerisque ac. Aliquam a
                                     orci ac est iaculis porta. Duis sollicitudin lectus sit amet velit
                                     condimentum lobortis.
                                    <inlineTag name="byline">-John Doe</inlineTag></inlineTag></inlineTag>
                        </text>
                    </textObject>
                </textObjects>
            </article>
        </issue>
    </publication>
</k4Export>
  

И вот XSLT, который я использую для преобразования. Я могу поместить заголовок и подстроку в заголовок, но я не могу извлечь их из содержимого. Я новичок в XSLT, поэтому буду признателен за любой совет. Элементы TextObject расположены по всему XML-документу, поэтому я намеренно использую очень общие селекторы XPath, чтобы добраться до них.

 <?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet 
    xmlns:default="http://www.vjoon.com/K4Export/1.4.2" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="2.0"
    exclude-result-prefixes="default">

    <!-- Output Content -->
    <xsl:template match="/">
        <html>
            <head>
                <title>Sample</title>
            </head>

            <body>

                <!-- Headline-->
                <xsl:variable name="headlines" select="//default:inlineTag[@name='headline']" />
                <xsl:choose>
                    <xsl:when test="$headlines">
                        <xsl:for-each select="$headlines">
                            <h1 class="headline"><xsl:value-of select="node()"/></h1>
                        </xsl:for-each>
                    </xsl:when>
                    <xsl:otherwise>
                        <h1 class="headline">Headline Absent</h1>
                    </xsl:otherwise>
                </xsl:choose>

                <!-- Bylines -->
                <xsl:variable name="bylines" select="//default:inlineTag[@name='byline']" />
                <xsl:choose>
                    <xsl:when test="$bylines">
                        <xsl:for-each select="$bylines">
                            <h2 class="byline"><xsl:value-of select="node()"/></h2>
                        </xsl:for-each>
                    </xsl:when>
                    <xsl:otherwise>
                        <h2 class="byline">Byline Absent</h2>
                    </xsl:otherwise>
                </xsl:choose>

                <div id="content">

                    <!-- body -->
                    <xsl:variable name="bodies" select="//default:inlineTag[@name='body']" />
                    <xsl:choose>
                        <xsl:when test="$bodies">
                            <xsl:for-each select="$bodies">
                                <p><xsl:value-of select="node()"/></p>
                            </xsl:for-each>
                        </xsl:when>
                    </xsl:choose>

                </div>

            </body>
        </html>

    </xsl:template>

</xsl:stylesheet>
  

Комментарии:

1. @user646151: Каким был бы точный желаемый результат для этого входного образца?

2. Хороший вопрос, 1. Смотрите мой ответ для простого и очевидного решения. Откройте шаблоны, откройте XSLT. 🙂

Ответ №1:

Я думаю, вы хотите что-то вроде этого (обратите внимание, что <xsl:for-each> теперь заменено на <xsl:apply-templates> и существуют разные шаблоны для обработки inlineTag элементов с разными значениями их name атрибута. В частности, шаблоны с пустым телом не копируют узел, которому они соответствуют, в выходные данные). Кроме этого, я не предпринимал никаких попыток иным образом переработать или улучшить ваш код — у него большой потенциал для улучшения.

Результат теперь не содержит ни заголовка, ни подписи.

 <xsl:stylesheet      xmlns:default="http://www.vjoon.com/K4Export/1.4.2"      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"      version="2.0"     exclude-result-prefixes="default">
    <!-- Output Content -->
    <xsl:template match="/">
        <html>
            <head>
                <title>Sample</title>
            </head>
            <body>
                <!-- Headline-->
                <xsl:variable name="headlines" select="//default:inlineTag[@name='headline']" />
                <xsl:choose>
                    <xsl:when test="$headlines">
                        <xsl:for-each select="$headlines">
                            <h1 class="headline">
                                <xsl:value-of select="node()"/>
                            </h1>
                        </xsl:for-each>
                    </xsl:when>
                    <xsl:otherwise>
                        <h1 class="headline">Headline Absent</h1>
                    </xsl:otherwise>
                </xsl:choose>
                <!-- Bylines -->
                <xsl:variable name="bylines" select="//default:inlineTag[@name='byline']" />
                <xsl:choose>
                    <xsl:when test="$bylines">
                        <xsl:for-each select="$bylines">
                            <h2 class="byline">
                                <xsl:value-of select="node()"/>
                            </h2>
                        </xsl:for-each>
                    </xsl:when>
                    <xsl:otherwise>
                        <h2 class="byline">Byline Absent</h2>
                    </xsl:otherwise>
                </xsl:choose>
                <div id="content">
                    <!-- body -->
                    <xsl:apply-templates select="//default:inlineTag[@name='body']" />
                </div>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="default:inlineTag[@name='body']">
      <p>
        <xsl:apply-templates/>
      </p>
    </xsl:template>

    <xsl:template priority="10" match=
    "default:inlineTag[@name='byline' or @name='headline']"/>

</xsl:stylesheet>