2013-05-20 2 views
0

Я новичок в XSLT, поэтому я прошу помощи. У меня есть несколько XML-документов, из которых приведен пример. Документы делятся на элементы <sub-doc(n)>, которые далее делятся на элементы <section>. В пределах секций находятся ZERO или более <heading> элементов, а также ONE или более <paragraph> элементов. Моя цель - обеспечить, чтобы каждый раздел имел самое большее ОДИН <heading> элемент, разделив те разделы, которые имеют более одного заголовка, в несколько разделов с одним заголовком в каждом. Когда это будет сделано, элементы <paragraph>, следующие сразу после <heading>, должны перейти с <heading> в новый <section>. Например, обратите внимание, что в следующем примере первый <section><sub-doc1> имеет два элемента <heading>. Мне нужно сломать этот элемент <section> в TWO <section> элементов, каждый со своим <heading> и последующие <paragraph> элементов.Как разбить дочерний узел на несколько дочерних узлов дочернего узла, каждый с одним поднаем

<document> 
<sub-doc1> 
    <section> <!-- This section needs to be split --> 
    <heading>Subdoc1 first heading text</heading> 
    <paragraph>A lot of text</paragraph> 
    <paragraph>Yet more text</paragraph> 
    <paragraph>More text</paragraph> 
    ... 
    <heading>Subdoc1 second heading text</heading> 
    <paragraph>Even more text</paragraph> 
    <paragraph>Some text</paragraph> 
    ... 
    </section> 
    <section> 
    <paragraph>Even more text</paragraph> 
    ... 
    </section> 
</sub-doc1> 
<sub-doc2> 
    <section> 
    <heading>Subdoc2, first heading text</heading> 
    <paragraph>A lot of text here</paragraph> 
    <paragraph>Yet more text here</paragraph> 
    <paragraph>Yet more text here</paragraph> 
    ... 
    </section> 
</sub-doc2> 
</document> 

То есть, преобразованный документ должен выглядеть следующим образом:

<document> 
<sub-doc1> 
    <section> <!-- This section got split into two sections --> 
    <heading>Subdoc1 first heading text</heading> 
    <paragraph>A lot of text</paragraph> 
    <paragraph>Yet more text</paragraph> 
    <paragraph>More text</paragraph> 
    ... 
    </section> 
    <section> <!-- This is a new section --> 
    <heading>Subdoc1 second heading text</heading> 
    <paragraph>Even more text</paragraph> 
    <paragraph>Some text</paragraph> 
    ... 
    </section> 
    <section> 
    <paragraph>Even more text</paragraph> 
    ... 
    </section> 
</sub-doc1> 
<sub-doc2> 
    <section> 
    <heading>Subdoc2, first heading text</heading> 
    <paragraph>A lot of text here</paragraph> 
    <paragraph>Yet more text here</paragraph> 
    <paragraph>Yet more text here</paragraph> 
    ... 
    </section> 
</sub-doc2> 
</document> 

Обратите внимание, что некоторые разделы не на всех <heading> элементов. В этих случаях эти разделы должны оставаться неизменными. Кроме того, некоторые разделы имеют только один <heading>. Эти разделы также должны оставаться неизменными. И все остальное в документе должно оставаться неизменным. Единственное преобразование, которое должно произойти, - это те случаи, когда <section> в любом месте документа содержит более одного <heading>.

Опять же, я новичок в XSLT и не могу получить голову вокруг XSL, который выполнит задачу. Спасибо за вашу помощь.

ответ

-1

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

Поскольку у вас также были разделы без заголовков, мне пришлось обрабатывать эти разделы по-разному.

<?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" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:template match="document"> 
    <document> 
     <!-- Select the sub-doc elements and print their names, then process their children --> 
     <xsl:for-each select="*"> 
     <xsl:element name="{local-name(.)}"> 
      <xsl:for-each select="section"> 
      <!-- For a section with 1 or more headings --> 
      <xsl:choose> 
       <xsl:when test="count(heading) &gt; 0"> 
       <!-- Print each section, heading and the paragraphs that follow --> 
       <xsl:for-each select="heading"> 
        <xsl:variable name="currentHeading" select="current()"/> 
        <section> 
        <heading> 
         <xsl:value-of select="."/> 
        </heading> 
        <!-- Pick paragraphs that follow current heading --> 
        <xsl:variable name="paragraphList" select="../paragraph[preceding-sibling::heading[1] = $currentHeading]"/> 
        <xsl:for-each select="$paragraphList"> 
         <paragraph> 
         <xsl:value-of select="."/> 
         </paragraph> 
        </xsl:for-each> 
        </section> 
       </xsl:for-each> 
       </xsl:when> 
       <xsl:otherwise> 
       <section> 
        <xsl:for-each select="paragraph"> 
        <paragraph> 
         <xsl:value-of select="."/> 
        </paragraph> 
        </xsl:for-each> 
       </section> 
       </xsl:otherwise> 
      </xsl:choose> 
      </xsl:for-each> 
     </xsl:element> 
     </xsl:for-each> 
    </document> 
    </xsl:template> 
</xsl:stylesheet> 

Niraj

0

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

Выход, который я показываю, соответствует вашему вводу образца с удаленными эллипсами.

Обратите внимание, что это решение требует, чтобы все section элементов, содержащих любые heading элементов имеют heading элемент в качестве первого ребенка. то есть нет paragraph элементов до первого heading. Если это предположение неверно, таблица стилей потребуется небольшое изменение.

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:strip-space elements="*"/> 
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> 

    <xsl:key name="paragraph-for-heading" match="paragraph" use="generate-id(preceding-sibling::heading[1])"/> 

    <xsl:template match="node()"> 
    <xsl:copy> 
     <xsl:apply-templates/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="section[heading]"> 
    <xsl:apply-templates select="heading"/> 
    </xsl:template> 

    <xsl:template match="heading"> 
    <section> 
     <xsl:copy> 
     <xsl:apply-templates/> 
     </xsl:copy> 
     <xsl:apply-templates select="key('paragraph-for-heading', generate-id())"/> 
    </section> 
    </xsl:template> 

</xsl:stylesheet> 

выход

<document> 
    <sub-doc1> 
     <section> 
     <heading>Subdoc1 first heading text</heading> 
     <paragraph>A lot of text</paragraph> 
     <paragraph>Yet more text</paragraph> 
     <paragraph>More text</paragraph> 
     </section> 
     <section> 
     <heading>Subdoc1 second heading text</heading> 
     <paragraph>Even more text</paragraph> 
     <paragraph>Some text</paragraph> 
     </section> 
     <section> 
     <paragraph>Even more text</paragraph> 
     </section> 
    </sub-doc1> 
    <sub-doc2> 
     <section> 
     <heading>Subdoc2, first heading text</heading> 
     <paragraph>A lot of text here</paragraph> 
     <paragraph>Yet more text here</paragraph> 
     <paragraph>Yet more text here</paragraph> 
     </section> 
    </sub-doc2> 
</document> 
+0

Спасибо, Бородин ...! Это работает отлично! Я очень ценю это. – user2399942

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

  • Нет связанных вопросов^_^