Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Problem with xsl style sheet 2

Status
Not open for further replies.

Ramnarayan

Programmer
Jan 15, 2003
56
0
0
US
Hi,

I am trying to parse the xsl sheet against this raw data as below:

This is a raw data:
<abs>
<sct>This is the section title</sct>
<p>This is a paragraph</p>
<sct> This is another section Title</sct>
<p>This is a second paragraph</p>
</abs>

Here is the xsl sheet i am using:

<xsl:template match="abs">
<xsl:element name="abstract">
<xsl:apply-templates select="sct"/>
<xsl:apply-templates select="p"/>
</xsl:element>
<!-- abstract -->
</xsl:template>
<xsl:template match="sct">
<xsl:element name="title">
<xsl:apply-templates select="node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="p">
<xsl:element name="p">
<xsl:apply-templates select="node()"/>
</xsl:element>
</xsl:template>

Now the output I am getting by running the xsl sheet on the raw data is as below:

<?xml version="1.0" encoding="utf-8"?>
<abstract><title>This is the section title</title>
<title> This is another section Title</title>
<p>This is a paragraph</p>
<p>This is a second paragraph</p>
</abstract>

Actually what I intended for it to appear is as below:

<?xml version="1.0" encoding="utf-8"?>
<abstract>
<title>This is the section title</title>
<p>This is a paragraph</p>
<title> This is another section Title</title>
<p>This is a second paragraph</p>
</abstract>

Can someone correct me where I am wrong in the xsl sheet so that I can make corrections. Actually this is the first time I am using xsl for processing raw data! Thanks for your help in this matter.
 
Here is your problem:
Code:
<xsl:apply-templates select="sct"/>
<xsl:apply-templates select="p"/>
This applies templates to all the <sct> elements within the <abstract> context element, so you get both. Then you do the same thing with the <p> elements.

If I understand your structure/requirements, then you must reflect the expected structure in your placement of apply-templates.

Code:
<xsl:template match="abs">
   <xsl:element name="abstract">
    <xsl:apply-templates select="sct"/>
   </xsl:element>
   <!-- abstract -->
 </xsl:template>
 <xsl:template match="sct">
  <xsl:element name="title">
   <xsl:apply-templates select="node()"/>
  </xsl:element>
  <xsl:apply-templates select="following-sibling::p[1]"/>
 </xsl:template>
 <xsl:template match="p">
  <xsl:element name="p">
   <xsl:apply-templates select="node()"/>
  </xsl:element>
 </xsl:template>
What this does is to select the <sct> elements as before, but then, within the context of the <sct> element, process the immediately adjacent <p> element (following-sibling::p[1]).

Tom Morrison
 
Thanks Tom. But the issue is that If <sct> is not present, then the <p> part will not be executed. Your code will work nicely for the example I gave. But when we consider the scenario that you have the case as below:
Code:
<abs>
<p> This is a paragraph</p>
<sct>This is a section Title</sct>
<p>This is a second para</p>
</abs>
In this case, the <p> that appears before <sct> is missing because there is no apply-templates for <p>. So how can I modify your code for this case? Thanks for enlightening me on the following-sibling::p[1]. I never heard this before and this is the first time I have learned. This is a great tip!
 
Ah, you need to start with an identity transform. Then you modify the identity transform by adding another template which matches the element you wish to rename. In the above-linked example, there is an identity transform that removes an element by name. This gives a hint at how to rename an element. You may also look here.

Tom Morrison
 
The identity transform as applied to your case:
Code:
<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>
<xsl:template match="abs">
  <abstract><xsl:apply-templates/></abstract>
</xsl:template>
<xsl:template match="sct">
  <title><xsl:apply-templates/></title>
</xsl:template>

Jon

"I don't regret this, but I both rue and lament it.
 
Thanks for the wonderful tip. However when I run the above xsl script you gave, I get the output below which is really what I want.

<?xml version="1.0" encoding="utf-8"?><abstract>
<p> This is a paragraph</p>
<title>This is a section Title</title>
<p>This is a second para</p>
</abstract>

But is there a way that we can drop out the
"<?xml version="1.0" encoding="utf-8"?>"

Any assistance will be greatly appreciated.
 
Thanks K5tm!. But currently it is going to process any thing that comes in the tag. if there are certain tags to be omitted from processing, what is the appropriate xslt equivalent term?

For eg,

<abs>
<p> This is a paragraph</p>
<sct>This is a section Title</sct>
<p>This is a second para</p>
<exc>this is to be excluded</exc>
</abs>

How can I drop the above tag <exc>...</exc> and should not be present in the converted xml.
 
Check the link to identity transform in my post of 28 Sep 07 17:16.

The purpose of the identity transform is to copy the input xml document to the output xml document. While that capability by itself is interesting, it is rarely used in 'real life'.

Instead, one uses the identity transform in a modified form as demonstrated above by Jon. His example shows how to pick out a specific element by name and rename it. The link I provided shows explicitly how to delete an element (and its subordinates) by its name. It is almost the same...

Tom Morrison
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top