title: xslt: create new node from mixed content within parent element
body: <p>I'm trying to write a template that will grab a mixture of text nodes and elements within a parent element and create a new node. I've done a lot of searching and couldn't find what I was looking for...so hopefully I'm not asking to basic a question. </p>
  
  <p>Here is a sample of xml I want to transform:</p>
  
  <pre><code>&lt;?xml version="1.0"?&gt;
  &lt;root&gt;
   &lt;para&gt;Here is some text that will ask users to enter a &lt;rule-line/&gt; [&lt;emph type="it"&gt;date&lt;/emph&gt;], and maybe their &lt;rule-line/&gt; [&lt;emph type="it"&gt;name&lt;/emph&gt;]. The text could come in different [&lt;emph type="it"&gt;order&lt;/emph&gt;] &lt;rule-line/&gt;, and their could be any number of instances.&lt;/para&gt;
  
  &lt;/root&gt;
  </code></pre>
  
  <p>I want to group the bracketed text and the rule into a new element like so:</p>
  
  <pre><code>&lt;entry&gt;[&lt;emph type"it"&gt;date&lt;/emph&gt;]&lt;/entry&gt;
  </code></pre>
  
  <p>I have a template that can identify the text I want to change, and I can change it, but I don't know how to add the text I want to the result tree and omit the old text. </p>
  
  <p>Here are the relevant templates: </p>
  
  <pre><code>&lt;xsl:template match="para"&gt;
   &lt;xsl:for-each select="* | text()"&gt;
    &lt;xsl:choose&gt;
  
     &lt;xsl:when test="self::rule-line and following-sibling::node()[1][starts-with(., ' [')] and string(node-name(following-sibling::node()[2])) = 'emph' and following-sibling::node()[3][starts-with(., ']')]"&gt;
      &lt;xsl:comment&gt;made match&lt;/xsl:comment&gt;
      &lt;xsl:call-template name="codeEntry"&gt;
       &lt;xsl:with-param name="rule" select="."/&gt;
       &lt;xsl:with-param name="openBracket" select="following-sibling::node()[1]"/&gt;
       &lt;xsl:with-param name="emphTag" select="following-sibling::node()[2]"/&gt;
       &lt;xsl:with-param name="closeBracketString" select="following-sibling::node()[3]"/&gt;
      &lt;/xsl:call-template&gt;
     &lt;/xsl:when&gt;
     &lt;xsl:otherwise&gt;
      &lt;xsl:copy-of select="."/&gt;
     &lt;/xsl:otherwise&gt;
    &lt;/xsl:choose&gt;
   &lt;/xsl:for-each&gt;
  
  &lt;/xsl:template&gt;
  
  
  &lt;xsl:template name="codeEntry"&gt;
  &lt;xsl:param name="rule"/&gt;
  &lt;xsl:param name="openBracket"/&gt;
  &lt;xsl:param name="emphTag"/&gt;
  &lt;xsl:param name="closeBracketString"/&gt;
  &lt;entry&gt;
  &lt;xsl:copy-of select="$openBracket"/&gt;
  &lt;xsl:copy-of select="$emphTag"/&gt;
  &lt;xsl:text&gt;] &lt;/xsl:text&gt;
  &lt;/entry&gt;
  &lt;xsl:value-of select="substring-after($closeBracketString, ']')"/&gt;
  
  &lt;/xsl:template&gt;
  </code></pre>
  
  <p>Obviously, the when statement grabs a group of nodes, but when each node goes through the otherwise block it gets copied to the result tree. I'm not really sure how to handle this since the para could have any number of these node groupings in any order, or none. (Once I figure this out I'll add another when block that deals with the bracketed text before the rule)</p>
  
  <p>I think creating a variable that tells the template to ignore the node is the way to go...but I'm a little foggy on the immutable variables and their scope...</p>
  
  <p>I was also trying to think of a way I could try to do this recursively...but that would require adding a start tag at one point, an end tag in another, or no tag if the node being processed is in the middle of the sequence...and I know that can get weird in xslt. </p>
  
  <p>Anyone run into this type of situation before? 
  thanks, 
  jason</p>
  
  <p>any ideas</p>