Solved

Select content and process child elements using XSLT

Posted on 2006-07-10
20
302 Views
Last Modified: 2013-11-19
Hello,

My XML looks like this..

<text>
Hello I am text
<child>and I am a child.</child>
more text.
</text>

I need to retrieve the content in <text> tag AND process it's child elements.

Any suggestions?

Thanks,
Kanishk.
0
Comment
Question by:kanishkpanwar
  • 14
  • 5
20 Comments
 

Author Comment

by:kanishkpanwar
ID: 17073684
there can be more than 1 child...
like <child1> <child2> etc etc
0
 
LVL 52

Expert Comment

by:Carl Tawn
ID: 17073806
Well, you would process the "text" node with something like:

    <xsl:template match="text">
        <p><xsl:value-of select="." /></p>
        <!-- Next line triggers processing of child nodes -->
        <xsl:apply-templates />
    </xsl:template>
0
 

Author Comment

by:kanishkpanwar
ID: 17073989
actually, I need the result to looks like this...

Hello I am text
<child>and I am a child.</child>
more text.
0
Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

 

Author Comment

by:kanishkpanwar
ID: 17074016
it could be like this too...

Hello I am text
<child>and I am a child.</child>
<child1>and I am a child1.</child1>
more text.

and so on..........
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 17074257
Hi kanishkpanwar,

if I understand you well,
this is what you need

    <xsl:template match="text">
        <xsl:copy-of select="node()|text()"/>
    </xsl:template>


Cheers!
0
 

Author Comment

by:kanishkpanwar
ID: 17074284
is there any way that I can process the child elements?

something like.....
<xsl:template match="child">
do something 1.
    </xsl:template>


<xsl:template match="child1">
do something 2.
</xsl:template>

and so on
0
 

Author Comment

by:kanishkpanwar
ID: 17074313
maybe use something like for-each?
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 17074455
no, then you would do

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

and make sure you have templates for the child nodes
(the text() will be copied anyway)

in this case it would be a good recommendation to add a mode

    <xsl:template match="text">
        <xsl:apply-templates select="node()|text()" mode="text-proc"/>
    </xsl:template>
    <xsl:template match="*" mode="text-proc">
        <!-- process the children here -->
    </xsl:template>

0
 

Author Comment

by:kanishkpanwar
ID: 17075284
will that effect my resultant XML if I already have
<xsl:template match="*"> in my XSLT ?
0
 

Author Comment

by:kanishkpanwar
ID: 17075295
I have increased the points because I have more questions and I better make it worth your time. :)
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 17075584
> will that effect my resultant XML if I already have

no, since you shield off the template from the other elements by using "mode"
there will be no conflict
0
 

Author Comment

by:kanishkpanwar
ID: 17075614
i try to process the tag <child> like this

   <xsl:element name="{local-name()}">
          <xsl:copy-of select="@*"/>
   <xsl:apply-templates />

but the <child> tag is not generated. ONLY text. :(
0
 

Author Comment

by:kanishkpanwar
ID: 17075638
</xsl:element>

is also there...missed it in copy paste.
0
 

Author Comment

by:kanishkpanwar
ID: 17075728
Here is the REAL XSLT i am working on...

<?xml version='1.0' encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns="-//FLSENATE/BILL XSD//EN">

  <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
  <xsl:preserve-space elements="ParagraphText Delete Add" />
 
 
  <xsl:template match="*">
        <xsl:choose>
              <xsl:when test="not(text()) and not(descendant::*[local-name() != 'Add'][text()])">
            </xsl:when>
            <xsl:otherwise>
                <xsl:element name="{local-name()}">
                        <xsl:copy-of select="@*"/>
                        <xsl:apply-templates />
              </xsl:element>
            </xsl:otherwise>
      </xsl:choose>
  </xsl:template>
 
  <xsl:template match="@*">
      <xsl:copy />
  </xsl:template>

  <!-- Remove Section specific attribute(s) -->
  <xsl:template match="Section">
        <xsl:element name="{local-name()}">
                  <xsl:apply-templates />
        </xsl:element>
  </xsl:template>
 
  <xsl:template match="Para">
              <xsl:element name="{local-name()}">
                     <xsl:copy-of select="@Sequence"/>
                     <xsl:copy-of select="@ParentSequence"/>
                  <xsl:apply-templates />
              </xsl:element>
  </xsl:template>

  <xsl:template match="ParaNumber">
  </xsl:template>

  <!-- Remove Section specific attribute(s) -->
  <xsl:template match="ParagraphText">
        <xsl:element name="{local-name()}">
              <xsl:variable name="PTEXT">
         <!--      <xsl:for-each select="descendant-or-self::*[name() != 'Add']/text()">-->
               <!--  <xsl:value-of select="." /> -->
               <xsl:apply-templates select="node()|text()" mode="text-proc"/>
               <!-- <xsl:apply-templates /> -->
               <!--</xsl:for-each>-->
              </xsl:variable>
              <xsl:value-of select="normalize-space($PTEXT)" />
        </xsl:element>
  </xsl:template>

  <xsl:template match="table">
        <xsl:apply-templates />
  </xsl:template>

  <!-- Remove all the added text -->
  <xsl:template match="Add">
        <xsl:text> </xsl:text>
  </xsl:template>

  <!-- Remove all the added text -->
  <xsl:template match="Add" mode="text-proc">
        <xsl:text> </xsl:text>
  </xsl:template>



  <!-- Add all the deleted text -->
  <xsl:template match="Delete" mode="text-proc">
<!--        <xsl:if test="position()&lt;last()">
          <xsl:text disable-output-escaping="yes"> </xsl:text>
          <xsl:value-of select="." />
        </xsl:if>
        <xsl:if test="position()=last()">
          <xsl:text disable-output-escaping="yes"> </xsl:text>
          <xsl:value-of select="." />
            <xsl:text disable-output-escaping="yes"> </xsl:text>
        </xsl:if>-->
    <xsl:text> </xsl:text><xsl:value-of select="." /><xsl:text> </xsl:text>
  </xsl:template>

  <xsl:template match="Delete" mode="text-proc">
<!--        <xsl:if test="position()&lt;last()">
          <xsl:text disable-output-escaping="yes"> </xsl:text>
          <xsl:value-of select="." />
        </xsl:if>
        <xsl:if test="position()=last()">
          <xsl:text disable-output-escaping="yes"> </xsl:text>
          <xsl:value-of select="." />
            <xsl:text disable-output-escaping="yes"> </xsl:text>
        </xsl:if>-->
    <xsl:text> </xsl:text><xsl:value-of select="." /><xsl:text> </xsl:text>
  </xsl:template>
 

  <!-- TO DO (Ask Yan): How to handle TypeOnly? -->
  <xsl:template match="TypeOnly">
  </xsl:template>

  <!-- TO DO (Ask Yan): Do these need to be deleted if they contain added text only? -->
  <xsl:template match="SuperScript | SubScript | Fraction | entry">
        <xsl:choose>
              <xsl:when test="not(text()) and (count(child::*) = count(child::Add))">
            </xsl:when>
            <xsl:otherwise>
              <xsl:element name="{local-name()}">
                       <xsl:copy-of select="@*"/>
                        <xsl:apply-templates />
              </xsl:element>
            </xsl:otherwise>
      </xsl:choose>
  </xsl:template>

 <xsl:template match="SuperScript | SubScript | Fraction | entry" mode="text-proc">
        <xsl:choose>
              <xsl:when test="not(text()) and (count(child::*) = count(child::Add))">
            </xsl:when>
            <xsl:otherwise>
              <xsl:element name="{local-name()}">
                       <xsl:copy-of select="@*"/>
                        <xsl:apply-templates />
              </xsl:element>
            </xsl:otherwise>
      </xsl:choose>
  </xsl:template>

  <xsl:template match="comment()">
  </xsl:template>

  <xsl:template match="processing-instruction()">
  </xsl:template>
 
  <xsl:template match="text()">
    <xsl:value-of select="normalize-space(.)"/>
  </xsl:template>

</xsl:stylesheet>
0
 

Author Comment

by:kanishkpanwar
ID: 17075732
here is the XML content that needs to be translated...

<?xml version="1.0" encoding="UTF-8"?>
<Section Source="FL Statute" Selection="Section,#7/#10/#13/#523896/#523919">
      <MetaText TextInNotes="false"/>
      <SectionNumber>7.221</SectionNumber>
      <CatchLine>Glades County, <Add>HELLO </Add>extension of boundary.</CatchLine>
      <SectionBody>
            <Para Sequence="(1)" CurrentSequence="(1)" Position="Begin" Order="0">
                  <ParaNumber>(1)</ParaNumber>
                  <ParagraphText>The existing boundaries of Glades County, Florida, be, and the same are enlarged and extended so <Delete>as to comprise and</Delete> include the following described additional <Add>HELLO </Add>territory now described as follows:</ParagraphText>
            </Para>
            <Para ParentSequence="(1)" Position="Begin" Order="1">
                  <ParagraphText Type="indent" SpaceBefore="false">All that portion of the S<Fraction>1/2</Fraction>of section 32, township 39 south, range 30 east lying east of Federal Highway No. 19 in Highlands County, Florida.</ParagraphText>
            </Para>
            <Para Sequence="(2)" CurrentSequence="(2)" Position="Begin" Order="0">
                  <ParaNumber>(2)</ParaNumber>
                  <ParagraphText>Said territory herein and hereby added to Glades County, Florida, shall, after June 13, 1949, be as much a portion of said Glades County, as if originally incorporated therein.</ParagraphText>
            </Para>
      </SectionBody>
</Section>
0
 

Author Comment

by:kanishkpanwar
ID: 17075745
when I use the current XSLT....I am not able to generate <Fraction> tags...only content comes out. :)
0
 
LVL 60

Accepted Solution

by:
Geert Bormans earned 500 total points
ID: 17076162
<xsl:element name="{local-name()}">
          <xsl:copy-of select="@*"/>
   <xsl:apply-templates />

but the <child> tag is not generated. ONLY text. :(

The problem is here:
 <!-- Remove Section specific attribute(s) -->
  <xsl:template match="ParagraphText">
        <xsl:element name="{local-name()}">
             <xsl:variable name="PTEXT">
         <!--     <xsl:for-each select="descendant-or-self::*[name() != 'Add']/text()">-->
             <!--  <xsl:value-of select="." /> -->
             <xsl:apply-templates select="node()|text()" mode="text-proc"/>
             <!-- <xsl:apply-templates /> -->
              <!--</xsl:for-each>-->
             </xsl:variable>
             <xsl:value-of select="normalize-space($PTEXT)" />
        </xsl:element>
  </xsl:template>

you store the text and the childnodes in a variable
and then you do an value-of select, which only gives you back the text content, not the childnodes

it is generally not a good idea to manipulate the whitespace nodes like this in XSLT
try to be cautious with the existing whitespace nodes,
or strip them all and add your own

cheers

0
 

Author Comment

by:kanishkpanwar
ID: 17076316
yeah...
I removed the variable bit and now the white space after "</Fraction> out" is getting lost. :(

MAN ! I am sooo tired...
0
 

Author Comment

by:kanishkpanwar
ID: 17076545
I think i'll do some research on my own and post a new question, IF needed.

thanks A LOT gertone for your help. :)
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 17076675
welcome, cheers
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
microsoft access - xml 10 74
Post xml via PHP Soap Client 3 62
The Best Website Creation Tools 14 76
TSQL Query Into Specific XML Format 3 25
The Confluence of Individual Knowledge and the Collective Intelligence At this writing (summer 2013) the term API (http://dictionary.reference.com/browse/API?s=t) has made its way into the popular lexicon of the English language.  A few years ago, …
SASS allows you to treat your CSS code in a more OOP way. Let's have a look on how you can structure your code in order for it to be easily maintained and reused.
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:
The viewer will learn how to dynamically set the form action using jQuery.

820 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question