Skip to content Skip to sidebar Skip to footer

Split A Node If It Has Certain Children

UPDATE: I think I have answered most of this question now, except the handling of . you can see my updates and current XSLT at the end of this post under the EDIT I

Solution 1:

It looks like your input is a little bit inconsistent with your output. (Is that the expected output, or the output you're getting now)? Chunks a-02 and a-03 have no <highlight> elements in the input, yet the output has <span class="highlight..."> elements. Also, chunk a-03 has text duplicated after the blockquote.

I believe I've produced a working solution that does everything in your example. Could you give this a try?

<xsl:stylesheetversion="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:outputmethod="xml"indent="yes"/><xsl:templatematch="/"><html><head><metahttp-equiv="Content-Type"content="text/html; charset=utf-8" /><title>Test</title></head><body><xsl:apply-templates/></body></html></xsl:template><xsl:templatematch="p | div"><xsl:variablename="breaks"select="note | pgBreak | quote" /><xsl:variablename="firstNonBreak"select="node()[count(. | $breaks) != count($breaks)][1]" /><xsl:variablename="nonBreaksAfterBreak"select="$breaks/following-sibling::node()[1][count(. | $breaks) != count($breaks)]" /><xsl:apply-templatesselect="$breaks | $firstNonBreak | $nonBreaksAfterBreak"mode="sectChild" /></xsl:template><!-- Template to output the chunk id attribute of a particular hierarchy --><xsl:templatename="ChunkId"><xsl:variablename="id"select="ancestor::*[../self::root]/@xml:id" /><xsl:iftest="$id"><xsl:attributename="data-chunkid"><xsl:value-ofselect="$id"/></xsl:attribute></xsl:if></xsl:template><!-- Splitting types - notes, page breaks, quotes --><xsl:templatematch="pgBreak"mode="sectChild"><divid="pg-{@pgId}"><xsl:value-ofselect="concat('Page ', @pgId)"/></div></xsl:template><xsl:templatematch="quote | note"mode="sectChild"><xsl:apply-templates /></xsl:template><!-- Receives the first node of each block of content outside of the splitting types
       and passes processing onto itself and siblings within its block--><xsl:templatematch="text() | highlight | note.ref | super"mode="sectChild"><xsl:variablename="content"><xsl:apply-templatesselect="."mode="buildContent" /></xsl:variable><xsl:iftest="normalize-space($content)"><xsl:call-templatename="Nest"><xsl:with-paramname="hierarchy"select="ancestor::*[not(self::root)]" /><xsl:with-paramname="content"select="$content" /></xsl:call-template></xsl:if></xsl:template><!-- Recursive template to output nodes from the top level down to content --><xsl:templatename="Nest"><xsl:paramname="topLevel"select="true()"/><xsl:paramname="hierarchy" /><xsl:paramname="content" /><xsl:variablename="top"select="$hierarchy[1]" /><xsl:variablename="remainder"select="$hierarchy[position() > 1]" /><!-- If there's a quote or note yet to come, don't output tags until we get there --><xsl:variablename="skipTags"select="boolean($remainder[self::quote or self::note])" /><!-- Recursive output is captured in a variable, to be output later in this template --><xsl:variablename="inside"><xsl:iftest="$hierarchy"><xsl:call-templatename="Nest"><xsl:with-paramname="topLevel"select="$topLevel and $skipTags" /><xsl:with-paramname="hierarchy"select="$remainder" /><xsl:with-paramname="content"select="$content" /></xsl:call-template></xsl:if></xsl:variable><xsl:choose><xsl:whentest="not($hierarchy)"><xsl:copy-ofselect="$content" /></xsl:when><xsl:whentest="$top/self::quote"><blockquote><xsl:call-templatename="ChunkId" /><xsl:copy-ofselect="$inside"/></blockquote></xsl:when><xsl:whentest="$top/self::note"><divid="note-{$top/@id}"><xsl:call-templatename="ChunkId" /><xsl:copy-ofselect="$inside"/></div></xsl:when><xsl:whentest="not($skipTags)"><xsl:elementname="{name($top)}"><xsl:iftest="$topLevel"><xsl:call-templatename="ChunkId" /></xsl:if><xsl:copy-ofselect="$inside"/></xsl:element></xsl:when><xsl:otherwise><xsl:copy-ofselect="$inside"/></xsl:otherwise></xsl:choose></xsl:template><xsl:templatematch="node()"mode="buildContent"><xsl:iftest="not(self::note or self::quote or self::pgBreak)"><!-- output this node --><xsl:apply-templatesselect="self::node()[normalize-space(.)]"mode="contentOutput" /><!-- pass processing onto next sibling --><xsl:apply-templatesselect="following-sibling::node()[1]"mode="buildContent" /></xsl:if></xsl:template><!-- Bottom level content - text, note refs, superscript, highlight--><xsl:templatematch="text()"mode="contentOutput"><xsl:copy-ofselect="."/></xsl:template><xsl:templatematch="note.ref"mode="contentOutput"><spanclass="noteRef"id="{@id}"><xsl:apply-templatesmode="contentOutput"/></span></xsl:template><xsl:templatematch="super"mode="contentOutput"><sup><xsl:apply-templatesmode="contentOutput"/></sup></xsl:template><xsl:templatematch="highlight"mode="contentOutput"><xsl:variablename="class"select="concat(name(.),'-',string(@rend))"/><spanclass="{$class}"><xsl:apply-templatesmode="contentOutput"/></span></xsl:template></xsl:stylesheet>

I believe the unclosed meta tags is a result of using method="html". You may need to use method="xml" to get closed meta tags. With method="html", the above transform produces the following output from your sample input:

<html><head><METAhttp-equiv="Content-Type"content="text/html; charset=utf-8"><title>Test</title></head><body><pdata-chunkid="a-01"><spanclass="highlight-italic">Bacon ipsum dolor sit amet</span> bacon chuck pastrami swine pork rump, shoulder beef ribs doner tri-tip
    tongue. Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin pastrami t-
    bone. Sirloin turducken short ribs t-bone andouille strip steak pork loin corned beef hamburger
    bacon filet mignon pork chop tail.
    <spanclass="noteRef"id="0001"><sup>1</sup></span></p><divid="note-0001"data-chunkid="a-01"><p>
        You may need to consult a <spanclass="highlight-italic">latin</span> butcher. Good Luck.
      </p></div><pdata-chunkid="a-01">
    Pork loin </p><divid="pg-01">Page 01</div><pdata-chunkid="a-01"> ribeye bacon pastrami drumstick sirloin, shoulder pig jowl. Salami brisket rump ham, tail
    hamburger strip steak pig ham hock short ribs jerky shank beef spare ribs. Capicola short ribs swine
    beef meatball jowl pork belly. Doner leberkas short ribs, flank chuck pancetta bresaola bacon ham
    hock pork hamburger fatback.
  </p><pdata-chunkid="a-02">
    Bacon ipsum dolor sit amet bacon chuck pastrami swine pork rump, shoulder beef ribs doner tri-tip
    tongue. Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin pastrami t-
    bone. Sirloin turducken short ribs t-bone andouille strip steak pork loin corned beef hamburger
    bacon filet mignon pork chop tail.
  </p><pdata-chunkid="a-03">
    Bacon ipsum dolor sit amet bacon chuck pastrami swine pork rump, shoulder beef ribs doner tri-tip
    tongue.
    </p><blockquotedata-chunkid="a-03"><p>
        Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin pastrami t-
        bone. Sirloin </p></blockquote><divid="pg-02">Page 02</div><blockquotedata-chunkid="a-03"><p>turducken short ribs t-bone andouille strip steak pork loin corned beef hamburger
        bacon filet mignon pork chop tail.
      </p></blockquote></body></html>

By changing the method to "xml" and manually adding the meta element to the transform, you can obtain the same result, but with the following <head>

<head><metahttp-equiv="Content-Type"content="text/html; charset=utf-8" /><title>Test</title></head>

Post a Comment for "Split A Node If It Has Certain Children"