The following XSLT fragment is used to wrap/tag the first and last text nodes with a given @audience attribute for highlighting.
<xsl:template match="text()">
<xsl:if test=". = ((((ancestor::*[contains(@audience,'FLAG_')])[last()])/descendant::text())[1])">
<xsl:call-template name="flagText"/>
</xsl:if>
<xsl-value-of select="."/>
<xsl:if test=". = ((((ancestor::*[contains(@audience,'FLAG_')])[last()])/descendant::text())[last()])">
<xsl:call-template name="flagText"/>
</xsl:if>
</xsl:template>
Pseudo-code:
Find the last (nearest) ancestor element that matches the flag criteria and then find the first and last text nodes that are descendants of that element and flag them.
The logic is correct but the implementation is wrong. This does indeed find the first and last text nodes but it is matching the values rather than the node. This is flagging any text node that has the same value as the first or last nodes.
Example:The quick brown fox jumped over the lazy dog.
Current output:[FLAG]The quick brown fox jumped over [FLAG]the lazy dog[FLAG].
The [1] and dog [last()] are properly flagged but it's also catching the word 'the' in the middle due to the string matching or being equal to the first.
Edit:
Expected (desired) output:[FLAG]The quick brown fox jumped over the lazy dog.[FLAG]
How can I reorganize my statement to only match the first and last nodes? I don't want to compare the strings I just want to select the first and last.
Edit:
Example Source XML
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept audience="Users" id="concept_lsy_5vg_kl"><title>Product ABC</title><conbody><p>This is a blurb about <ph>Product ABC</ph>. Since the text in the phrase (ph) matches the text node in the title (first text node) it will be flagged. I only want the first and last nodes flagged. Basically, I don't want to compare the contents of the nodes. <ph audience="Users">I also need to support inline cases such as this one. </ph>I just want the flags before and after the first and last text nodes for each audience match.</p></conbody></concept>
Example XSLT
<?xml version='1.0' encoding='UTF-8'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" >
<xsl:output method="text" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="text()">
<xsl:if test=". = ((((ancestor::*[contains(@audience,'Users')])[last()])/descendant::text())[1])">
<xsl:text>[USERS]</xsl:text>
</xsl:if>
<xsl:value-of select="."/>
<xsl:if test=". = ((((ancestor::*[contains(@audience,'Users')])[last()])/descendant::text())[last()])">
<xsl:text>[/USERS]</xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Current Output
[USERS]Product ABCThis is a blurb about [USERS]Product ABC. Since the text in the phrase (ph) matches the text node in the title (first text node) it will be flagged. I only want the first and last nodes flagged. Basically, I don't want to compare the contents of the nodes. [USERS]I also need to support inline cases such as this one. [/USERS]I just want the flags before and after the first and last text nodes for each audience match.[/USERS]
Desired Output [USERS]Product ABCThis is a blurb about Product ABC. Since the text in the phrase (ph) matches the text node in the title (first text node) it will be flagged. I only want the first and last nodes flagged. Basically, I don't want to compare the contents of the nodes. [USERS]I also need to support inline cases such as this one. [/USERS]I just want the flags before and after the first and last text nodes for each audience match.[/USERS]
Thanks.