Subject: Re: [xsl] Moving element up hierarchy unless text nodes From: "Wendell Piez wapiez@xxxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Mon, 2 Mar 2015 19:10:49 -0000 |
Hi James, So, try this. It works by assigning 'pb' elements to ancestors that consider them 'leading' (start the element off) or 'trailing'. They can be retrieved from (for) said ancestor using a key. Lightly tested. <xsl:template match="comment() | processing-instruction() | text() | @*"> <xsl:copy-of select="."/> </xsl:template> <xsl:template match="*"> <xsl:copy-of select="key('leading-pb',generate-id())"/> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> <xsl:copy-of select="key('trailing-pb',generate-id())"/> </xsl:template> <xsl:template match="pb"> <!-- Only copy the pb if no ancestor considers it 'leading' or 'trailing'. --> <xsl:if test="empty( ancestor::*/(key('leading-pb',generate-id()) | key('trailing-pb',generate-id())) intersect . ) "> <xsl:copy-of select="."/> </xsl:if> </xsl:template> <xsl:key name="leading-pb" match="pb"> <xsl:apply-templates select="." mode="leading-pb"/> </xsl:key> <xsl:key name="trailing-pb" match="pb"> <xsl:apply-templates select="." mode="trailing-pb"/> </xsl:key> <xsl:template match="body/*" mode="leading-pb trailing-pb"> <xsl:sequence select="generate-id()"/> </xsl:template> <xsl:template match="*" mode="leading-pb"> <xsl:choose> <xsl:when test="empty(preceding-sibling::*/(. except self::pb) | preceding-sibling::text()[matches(.,'\S')])"> <xsl:apply-templates select=".." mode="leading-pb"/> </xsl:when> <xsl:otherwise> <xsl:sequence select="generate-id()"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="*" mode="trailing-pb"> <xsl:choose> <xsl:when test="empty(following-sibling::*/(. except self::pb) | following-sibling::text()[matches(.,'\S')])"> <xsl:apply-templates select=".." mode="trailing-pb"/> </xsl:when> <xsl:otherwise> <xsl:sequence select="generate-id()"/> </xsl:otherwise> </xsl:choose> </xsl:template> Feel free to ask for any explanation needed. It *seems* to work (although I often do not trust my lying eyes) ... :-) Cheers, Wendell On Fri, Feb 27, 2015 at 6:51 PM, James Cummings james@xxxxxxxxxxxxxxxxx <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote: > > Hi there. > > We've been looking at canonicalising use of <pb/> in a large collection of > TEI P5 XML texts. What we want to do is move this up the hierarchy unless > there is text before or after it only stopping when there is a sibling > element with textual content or when it hits the body/back/front elements. > i.e. someone might have encoded: > > > ====input==== > <body> > <div> > <lg> > <l><pb n="1"/> some text here</l> > <l>some text here <pb n="2"/></l> > </lg> > <lg> > <l>some text <pb n="3"/> some text</l> > <anchor xml:id="test"/> > <l><pb n="4"/>some text here</l> > <l>some text here <pb n="5"/></l> > <anchor xml:id="test2"/> > </lg> > </div> > <div> > <head>Some Text</head> > <lg> > <!-- A comment here --> > <l><pb n="6"/>Some text</l> > <l>Some text<pb n="7"/></l> > </lg> > </div> > </body> > ===== > > And what we'd want to end up with is: > > ===== > <body> > <pb n="1"/> > <div> > <lg> > <l> some text here</l> > <l>some text here </l> > </lg> > <pb n="2"/> > <lg> > <l>some text <pb n="3"/> some text</l> > <pb n="4"/> > <anchor xml:id="test"/> > <l>some text here</l> > <l>some text here </l> > <anchor xml:id="test2"/> > </lg> > </div> > <pb n="5"/> > <div> > <head>Some Text</head> > <pb n="6"/> > <lg> > <!-- A comment here --> > <l>Some text</l> > <l>Some text</l> > </lg> > </div> > <pb n="7"/> > </body> > ===== > > So as the <pb/> has text before/after it, it stays where it is. It should > move to the level in the hierarchy where its preceding-sibling::node()[1] > has text, passing over other empty elements or comments. (Of course, as you > might expect) the markup could be any element names, I just use div/lg/l > here because it is short and nicely hierarchicial as an example. My approach > so far has been, on every element to try to test if there is text() between > where I currently am and the following::pb[1] by selecting everything > between the start and the pb and looking at its normalised string-length. > But so far these tests aren't working right, and I haven't even got my head > round how to do it in reverse for <pb/> at the end. > > Has anyone done something like this before that I could look at? Any > suggestions? > > Thanks for any help! > > -James Cummings > XSL-List info and archive > EasyUnsubscribe (by email) -- Wendell Piez | http://www.wendellpiez.com XML | XSLT | electronic publishing Eat Your Vegetables _____oo_________o_o___ooooo____ooooooo_^
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] XSL-List Guidelines, B Tommie Usdin btusd | Thread | Re: [xsl] Moving element up hierarc, Wendell Piez wapiez@ |
[xsl] XSL-List Guidelines, B Tommie Usdin btusd | Date | Re: [xsl] Moving element up hierarc, Wendell Piez wapiez@ |
Month |