Norman Fight
Norman Fight

Reputation: 11

XSLT Select Node from Parameter and merge to XML

i have just created a XSL transformation where i am transform Xml to xHTML and back. It is my first time working with XSLT. Now i am building the "back part" a reverse transformation and there i am stuck.

Introduction/Overview

So the base XML contains two nodes (frags) where i am looking for:

<frag id="10" name="Editable_Fragment" >
 <child id="11"></child>
</frag>
<frag id="20" name="Editable_Fragment2">
 <child id="21"></child>
</frag>

Btw there are a lot of fragments inside this XML but i just looking for "editable" ones! So i have create a XSLT like this:

<?xml version="1.0"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:template match="/">

  <xsl:apply-templates select="/review-case/review-document/review-channel/content/region/section/frag[@name='Editable_Fragment']/node()"/>
  <xsl:apply-templates select="/review-case/review-document/review-channel/content/region/section/frag[@name='Editable_Fragment2']/node()"/>

</xsl:template>

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

The content of both nodes are hold together in a rich text editor as a string! The content looks like this:

<child id="11" name="Editable_Fragment">....data...</child>
<child id="21" name="Editable_Fragment">....data...</child>

In the rich text editor i am changing some data of both nodes and afterwards i want to update the data with a so called reverse transformation.

Reverse Transformation Issue

The string with both "child" tags will be used for further processing within a parameter mpTransformParameters. I have to use this parameter. I know with the following XSLT code i am just updating frag id="10" with child id="11" and child id="21".

My Question is, how can i merge back updated child id="11" to "frag id=10" and child id="21 to "frag id=20" if both are together in on string?

"Reverse" XSLT:

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

<xsl:template match="review-case/review-document/review-channel/content/region/section/frag/child[@name='Editable_Fragment']">
 <xsl:value-of select="$mpTransformParameters" disable-output-escaping="yes"/>          
</xsl:template>

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

</xsl:stylesheet>

Thanks a lot

Upvotes: 1

Views: 441

Answers (1)

Valdi_Bo
Valdi_Bo

Reputation: 31011

Try such XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" omit-xml-declaration="yes"/>
  <xsl:param name="mpTransformParameters">
    &lt;child id="11" name="Editable_Fragment"&gt;..data 11..&lt;/child&gt;
    &lt;child id="21" name="Editable_Fragment"&gt;..data 22..&lt;/child&gt;
  </xsl:param>

  <xsl:template match="section">
    <xsl:variable name="tbl"
      select="tokenize($mpTransformParameters, '&lt;/child&gt;')"/>
    <xsl:copy>
      <xsl:for-each select="$tbl">
        <xsl:analyze-string select="."
          regex="id=&quot;(\d+)&quot;.*&gt;(.*)">
          <xsl:matching-substring>
            <xsl:variable name="id" select="number(regex-group(1)) - 1"/>
            <xsl:variable name="txt" select="regex-group(2)"/>
            <xsl:variable name="nm">
              <xsl:if test="$id=10"><xsl:text>Editable_Fragment</xsl:text></xsl:if>
              <xsl:if test="$id=20"><xsl:text>Editable_Fragment2</xsl:text></xsl:if>
            </xsl:variable>
            <xsl:element name="frag">
              <xsl:attribute name="id" select="$id"/>
              <xsl:attribute name="name" select="$nm"/>
              <xsl:value-of select="$txt"/>
            </xsl:element>
          </xsl:matching-substring>
        </xsl:analyze-string>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="@* | node()">
    <xsl:copy><xsl:apply-templates select="@* | node()"/></xsl:copy>
  </xsl:template>
</xsl:stylesheet>

I deliberately choose XSLT 2.0, because it would be too tedious to write it in version 1.0.

For the purpose of the test run, I assigned a sample value to mpTransformParameter.

I prepared slightly simplified XML input with dummy content of section element, as you wrote, that the actual content is in mpTransformParameters:

<region>
  <section>Dummy content
  </section>
</region>

Using it, I got the following result:

<region>
  <section>
      <frag id="10" name="Editable_Fragment">..data 11..</frag>
      <frag id="20" name="Editable_Fragment2">..data 22..</frag>
   </section>
</region>

Upvotes: 1

Related Questions