Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old March 10th, 2010, 08:56 AM
Authorized User
 
Join Date: Feb 2009
Posts: 31
Thanks: 6
Thanked 1 Time in 1 Post
Send a message via MSN to anil_yadav26@hotmail.com
Default [XSLT 2.0] check and fetch the value from external xml file

Hi,

I have different XML files of a book, e.g. fm, part, chapter, BM, index, etc.... In the file index.xml there is a tag given with name "link" with "start" attribute which contains unique id, e.g. <link start="c51351-963">. Now I have to check whether the @start id is available in the rest xml files with the tag name <target id="[id of @start]". If it is available then I have to check whether the parent tag is "fn". If the parent tag is "fn" then I have to create a new attribute in the "link" tag, in index.xml, like this <link start="c51351-963" TBlabel="fn3">.

I working with the approach where I'm storing all the xml files into a variable $docs and comparing the link id with target id. If its a match then it check the parent of matched <target id="">. I'm not sure is this the right way to check the parent "$docs//target[@id]/parent::fn" and geting the @label contents "$docs//target[@id]/parent::fn/label".

Please suggest.

Thanks,
Anil Yadav



XML files:
index.xml
Code:
<index-list>
<index-item><index-entry>Abou</index-entry><link start="c51351-963">236</link></index-item>
</index-list>


rest-files of book
(I'm putting the coding of the matched file)
Code:
<?xml version="1.0" encoding="UTF-8"?>
<book>
<main>
<chapter>
<title>Integration</title>
<body/>
<back>
<fn-group>
<fn><target id="c51351-961"/><label>1</label><p/></fn>
<fn><target id="c51351-962"/><label>2</label><p/></fn>
<fn><target id="c51351-963"/><label>3</label><p/></fn>
<fn><target id="c51351-964"/><label>4</label><p/></fn>
<fn><target id="c51351-965"/><label>5</label><p/></fn>
<fn><target id="c51351-966"/><label>6</label><p/></fn>
</fn-group>
</back>
</chapter>
</main>
</book>


Output required
index.xml
Code:
<index-list>
<index-item><index-entry>Abou</index-entry><link start="c51351-963" TBlabel="fn.3">236</link></index-item>
</index-list>

XSLT

Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="2.0">
    <xsl:variable name="docs" select="collection('file:///E:/Download/Index Sample/XML Sample/?select=*.xml')"/>
 <xsl:template match="index-item">
  <index-item>
   <xsl:copy-of select="@*"/>
   <xsl:if test="index-entry">
    <xsl:apply-templates select="index-entry"/>
   </xsl:if>
   <xsl:for-each select="link">
    <xsl:choose>
     <xsl:when test="(@start=$docs//target/@id) and ($docs//target[@id]/parent::fn)">
       <xsl:variable name="TBlabel" select="$docs//target[@id]/parent::fn/label"/>
      <link>
       <xsl:copy-of select="@*"/>
       <xsl:attribute name="TBlabel">fn.<xsl:value-of select="normalize-space($TBlabel)"/></xsl:attribute>
       <xsl:value-of select="."/>
      </link>
     </xsl:when>
     <xsl:otherwise>
      <link>
       <xsl:copy-of select="@*"/>
       <xsl:value-of select="."/>
      </link>
     </xsl:otherwise>
    </xsl:choose>
   </xsl:for-each>
  </index-item>
 </xsl:template>
</xsl:stylesheet>
 
Old March 10th, 2010, 09:12 AM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

I think you can shorten
Code:
   <xsl:for-each select="link">
    <xsl:choose>
     <xsl:when test="(@start=$docs//target/@id) and ($docs//target[@id]/parent::fn)">
       <xsl:variable name="TBlabel" select="$docs//target[@id]/parent::fn/label"/>
      <link>
       <xsl:copy-of select="@*"/>
       <xsl:attribute name="TBlabel">fn.<xsl:value-of select="normalize-space($TBlabel)"/></xsl:attribute>
       <xsl:value-of select="."/>
      </link>
     </xsl:when>
     <xsl:otherwise>
      <link>
       <xsl:copy-of select="@*"/>
       <xsl:value-of select="."/>
      </link>
     </xsl:otherwise>
    </xsl:choose>
   </xsl:for-each>
to
Code:
   <xsl:for-each select="link">
     <link>
       <xsl:copy-of select="@*"/>
         <xsl:if test="@start = $docs//fn/target/@id">
           <xsl:attribute name="TBLabel" select="concat('fn.', normalize-space($docs//fn[target/@id = current()/@start]/label))"/>
         </xsl:if>
       <xsl:value-of select="."/>
     </link>
   </xsl:for-each>
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
 
Old March 10th, 2010, 01:00 PM
Authorized User
 
Join Date: Feb 2009
Posts: 31
Thanks: 6
Thanked 1 Time in 1 Post
Send a message via MSN to anil_yadav26@hotmail.com
Default

Hi Martin,

Thanks for your reply and short code but I keep it long as I have to put many conditions according to link attribute which I still have to code.....The code is perfectly working but it get fail if any target id comes under child of <fn> tag. Could you please suggest how to deal with that. I tried to put double slash in
Code:
     <xsl:if test="@start = $docs//fn//target/@id">
and

Code:
<xsl:attribute name="TBLabel" select="concat('fn.', normalize-space($docs//fn[//target/@id = current()/@start]/label))"/>
Its woking fine for IF condition but showing an error on Attribute.

error: A sequence of more than one item is not allowed as the first argument of normalize-space() ("1", "2", ...)
 
Old March 10th, 2010, 01:14 PM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

Are you sure you want to start the predicate (the expression in square brackets) with "//"? That is rather odd. Could even be the cause of the problem you have.
And you said 'fn' is the parent element of the 'target' element so why do you use '//' in 'fn//target'? 'fn/target' should suffice.
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
 
Old March 11th, 2010, 04:47 AM
Authorized User
 
Join Date: Feb 2009
Posts: 31
Thanks: 6
Thanked 1 Time in 1 Post
Send a message via MSN to anil_yadav26@hotmail.com
Default

Hi Martin,

After running your code, which is perfectly working on given sample files, I noticed that some of the TAGs are not generating the attribute TBLabel properly. It is generating like this TBLabel="fn." in which there is no label number is generating. When I cross check the same against the xml files I noticed that <target> tag is appearing under the child tag <p> of <fn>.

Now I have two conditions, <target> tag can be child of <fn> and it can be child of child of <fn> tag. It means <fn> can be parent or ancestor of <target> tag.

Please could suggest a solution on this.

Thanks,
Anil Yadav

Last edited by [email protected]; March 11th, 2010 at 04:55 AM.. Reason: sentence
 
Old March 11th, 2010, 05:54 AM
Friend of Wrox
 
Join Date: Jun 2008
Posts: 291
Thanks: 9
Thanked 29 Times in 29 Posts
Thumbs up

Try with the below:
Code:
<xsl:template match="index-item">
  <index-item>
   <xsl:copy-of select="@*"/>
   <xsl:if test="index-entry">
    <xsl:apply-templates select="index-entry"/>
   </xsl:if>
   <xsl:for-each select="link">
   <link>
       <xsl:copy-of select="@*"/>
    <xsl:variable name="start" select="@start"/>
   <xsl:for-each select="$docs//fn-group//target">
     
         <xsl:if test="$start = @id">
   
           <xsl:attribute name="TBLabel" select="concat('fn.', normalize-space(following::label[1]))"/>
      
         </xsl:if>
       </xsl:for-each>
     </link>
   </xsl:for-each>
  </index-item>
 </xsl:template>
__________________
Rummy
 
Old March 11th, 2010, 10:11 AM
Authorized User
 
Join Date: Feb 2009
Posts: 31
Thanks: 6
Thanked 1 Time in 1 Post
Send a message via MSN to anil_yadav26@hotmail.com
Default

Hi Rummy,

Thanks for your post!

The code is now generating the label but now it is generating the label of next <fn>. Suppose in sequence it should generate "fn.73" but it is generating "fn.74"(which a label of next <fn>).

Please suggest.
 
Old March 12th, 2010, 01:39 AM
Friend of Wrox
 
Join Date: Jun 2008
Posts: 291
Thanks: 9
Thanked 29 Times in 29 Posts
Thumbs up

Please post the minimal but relevant xml input, we shall try.
__________________
Rummy
 
Old March 12th, 2010, 04:27 AM
Authorized User
 
Join Date: Feb 2009
Posts: 31
Thanks: 6
Thanked 1 Time in 1 Post
Send a message via MSN to anil_yadav26@hotmail.com
Default

Hi Rummy,

Below is the xml.

index.xml
Code:
<book>
<index-list>
<index-item><index-entry>SNUPAT v High Authority</index-entry>&#x2002;<link start="c12151-ind-3805">411</link></index-item>
<index-item><index-entry>Morson v Netherlands</index-entry>&#x2002;<link start="c12151-ind-4189">462</link></index-item>
</index-list>
</book>
$docs (chapter 1 and 2)
Chapter 1

Code:
<?xml version="1.0" encoding="UTF-8"?>
<book>
    <main>
        <chapter>
            <title>Integration</title>
            <body/>
            <back>
                <fn-group>
                    <fn><label>73<char>   </char></label><p>It <target id="c12151-ind-3805"/>was first set out in Joined Cases 42/59 and 49/59 <emphasis>SNUPAT</emphasis> v <emphasis>High Authority</emphasis> [1961] ECR 109.</p></fn>
                    <fn><label>74<char>   </char></label><p>Case C-345/06 <emphasis>Heinrich</emphasis>, Judgment of 10 March 2009, para. 44.</p></fn>
                    <fn><label>75<char>   </char></label><p>Case 84/78 <emphasis>Tomadini</emphasis> v <emphasis>Amminstrazione delle Finanze dello Stato</emphasis> [1979] ECR 1801.</p></fn>
                    <fn><label>76<char>   </char></label><p>Case 63/83 <emphasis>R</emphasis> v <emphasis>Kirk</emphasis> [1984] ECR 2689.</p></fn>
                </fn-group>
            </back>
        </chapter>
    </main>
</book>

Chapter 2
Code:
<book>
    <main>
        <chapter>
            <title>Integration2</title>
            <body/>
            <back>
                <fn-group>
                    <fn><label>75<char>   </char></label><target id="c12151-ind-4189"/><p>Joined Cases C-64/96 and C-65/96 <emphasis>Uecker and Jacquet</emphasis> [1997] ECR I-3171; see also Joined Cases 35/82 and 36/82 <emphasis>Morson and Jhanjan</emphasis> v <emphasis>Netherlands</emphasis> [1982] ECR 3723.</p></fn>
                    <fn><label>76<char>   </char></label><p>See <citation type="journal"><author type="author"><name><given-names>A.</given-names> <surname>Tryfonidou</surname></name></author>, ‘<article-title>Reverse Discrimination in Purely Internal Situations: An Incongruity in a Citizens’ Europe</article-title>’ (<year>2008</year>) <volume>35</volume> <journal-title>IEI</journal-title> <startpage>43</startpage></citation>; <citation type="journal"><author type="author"><name><given-names>N. Nic</given-names> <surname>Shuibhne</surname></name></author> ‘<article-title>Free Movement of Persons and the Wholly Internal Rule: Time to Move On?</article-title>’ (<year>2002</year>) <volume>39</volume> <journal-title>CMLRev</journal-title>. <startpage>731</startpage></citation>.</p></fn>
                    <fn><label>77<char>   </char></label><p><emphasis>Ibid.</emphasis></p></fn>
                </fn-group>
            </back>
        </chapter>
    </main>
</book>
Output generating
Code:
<index-item><index-entry>SNUPAT v High Authority</index-entry><link start="c12151-ind-3805" TBLabel="fn.74"/></index-item>
<index-item><index-entry>Morson v Netherlands</index-entry><link start="c12151-ind-4189" TBLabel="fn.76"/></index-item>
Output required
Code:
<index-item><index-entry>SNUPAT v High Authority</index-entry><link start="c12151-ind-3805" TBLabel="fn.73"/></index-item>
<index-item><index-entry>Morson v Netherlands</index-entry><link start="c12151-ind-4189" TBLabel="fn.75"/></index-item>
___________
Anil Yadav
 
Old March 12th, 2010, 05:08 AM
Friend of Wrox
 
Join Date: Jun 2008
Posts: 291
Thanks: 9
Thanked 29 Times in 29 Posts
Thumbs up

Replace "following::label[1]" to "preceding::label[1]" and check.
__________________
Rummy
The Following User Says Thank You to mrame For This Useful Post:
[email protected] (March 12th, 2010)





Similar Threads
Thread Thread Starter Forum Replies Last Post
Convert XML file using XSLT sushil.sharma75 XSLT 13 November 20th, 2009 01:59 PM
Modifiying XML File using XSLT brianlan XSLT 1 October 2nd, 2007 03:14 PM
insert data param into xml from external file alexshiell XSLT 0 January 24th, 2006 01:47 PM
merge two xml file and make new xml using xslt ketan XSLT 0 September 21st, 2004 08:48 AM
Merge XML files into a xml file using xslt lxu XML 4 November 6th, 2003 06:01 PM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.