Solved

Select content and process child elements using XSLT

Posted on 2006-07-10
20
294 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
 

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
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Tech Writing Terminology - Pane or Panel? 8 68
Excel VBA and XML - traversing the nodes 2 57
Microsoft Edge 9 83
Change to event 1 75
This article covers the basics of the Sass, which is a CSS extension language. You will learn about variables, mixins, and nesting.
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 …
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 look for a specific file type in a local or remote server directory using PHP.

744 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now