Solved

Select content and process child elements using XSLT

Posted on 2006-07-10
20
304 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Is Your Team Achieving Their Full Potential?

74% of employees feel they are not achieving their full potential. With Linux Academy, not only will you strengthen your team's core competencies but also their knowledge of of the newest IT topics.

With new material every week, we'll make sure that you stay ahead of the game.

 

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

Get HTML5 Certified

Want to be a web developer? You'll need to know HTML. Prepare for HTML5 certification by enrolling in July's Course of the Month! It's free for Premium Members, Team Accounts, and Qualified Experts.

Question has a verified solution.

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

Introduction Knockoutjs (Knockout) is a JavaScript framework (Model View ViewModel or MVVM framework).   The main ideology behind Knockout is to control from JavaScript how a page looks whilst creating an engaging user experience in the least …
I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…
Video by: Mark
This lesson goes over how to construct ordered and unordered lists and how to create hyperlinks.
Suggested Courses

623 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