Re: [xsl] FW: XSLT newbie

Subject: Re: [xsl] FW: XSLT newbie
From: "Mukul Gandhi" <gandhi.mukul@xxxxxxxxx>
Date: Wed, 27 Dec 2006 22:22:52 +0530
I am assuming you want to solve this problem using XSLT 1.0. I have
used the nodeset extension function in my solution below.

Here is a solution you might find useful.

The input XMLs are:

paths.xml
--------------

<Paths>
 <path1>books.book.author.name</path1>
 <path2>books.book.name</path2>
</Paths>

input.xml
-------------

<books>
 <book>
   <name>a1</name>
   <price>10</price>
   <author>
     <name>b1</name>
     <gender>m</gender>
   </author>
 </book>
 <book>
   <name>a2</name>
   <price>10</price>
   <author>
     <name>b2</name>
     <gender>f</gender>
   </author>
 </book>
</books>

The stylesheet is:

test.xsl
-----------

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                      xmlns:xalan="http://xml.apache.org/xalan";
                      version="1.0">

<xsl:output method="text" />

<xsl:variable name="doc2" select="document('input.xml')" />

<xsl:template match="/Paths">

 <!-- iterate over all child elements -->
 <xsl:for-each select="*">
   <!-- strore path in a variable -->
   <xsl:variable name="path1">
     <xsl:call-template name="ConstructPath1">
       <xsl:with-param name="x" select="." />
       <xsl:with-param name="result" select="''" />
     </xsl:call-template>
   </xsl:variable>

   <!-- accumulate output -->
   <xsl:variable name="rtf">
     <xsl:for-each select="$doc2//*">
       <!-- strore path in a variable -->
       <xsl:variable name="path2">
         <xsl:call-template name="ConstructPath2">
           <xsl:with-param name="x" select="." />
           <xsl:with-param name="result" select="''" />
         </xsl:call-template>
       </xsl:variable>

       <!-- compare paths -->
       <xsl:if test="$path1 = $path2">
         <dummy><xsl:value-of select="$path1" /></dummy>
       </xsl:if>
     </xsl:for-each>
   </xsl:variable>

   <!-- eliminate duplicates from accumulated output; and print result -->
   <xsl:for-each select="xalan:nodeset($rtf)/dummy[not(. =
preceding-sibling::*)]">
     <xsl:value-of select="." /> : exists <xsl:text>&#xa;</xsl:text>
   </xsl:for-each>
 </xsl:for-each>
</xsl:template>

<!-- construct path, given a string of form x.y.z -->
<xsl:template name="ConstructPath1">
 <xsl:param name="x" />
 <xsl:param name="result" />

 <xsl:choose>
   <xsl:when test="contains($x, '.')">
     <xsl:call-template name="ConstructPath1">
       <xsl:with-param name="x" select="substring-after($x, '.')" />
       <xsl:with-param name="result" select="concat($result, '/',
substring-before($x, '.'))" />
     </xsl:call-template>
   </xsl:when>
   <xsl:otherwise>
     <xsl:choose>
       <xsl:when test="string-length($x) &gt; 0">
         <xsl:value-of select="concat($result, '/', $x)" />
       </xsl:when>
       <xsl:otherwise>
         <xsl:value-of select="$result" />
       </xsl:otherwise>
     </xsl:choose>
   </xsl:otherwise>
 </xsl:choose>
</xsl:template>

<!-- construct element path, given an element node as input -->
<xsl:template name="ConstructPath2">
 <xsl:param name="x" />
 <xsl:param name="result" />

 <xsl:choose>
   <xsl:when test="$x/..">
     <xsl:call-template name="ConstructPath2">
       <xsl:with-param name="x" select="$x/.." />
       <xsl:with-param name="result" select="concat('/',
local-name($x), $result)" />
     </xsl:call-template>
   </xsl:when>
   <xsl:otherwise>
     <xsl:value-of select="$result" />
   </xsl:otherwise>
 </xsl:choose>
</xsl:template>

</xsl:stylesheet>

This when run with Xalan-J 2.7.1 as following:

java org.apache.xalan.xslt.Process -in paths.xml -xsl test.xsl

produces output:

/books/book/author/name : exists
/books/book/name : exists

Hope this helps.

On 12/27/06, Thimmegowda, Balaji <balaji_thimmegowda@xxxxxxxxx> wrote:
Hi,

I am trying to achieve the following using XSLT :

I apply a XSLT on my source XML to get a path - say, books/author/name

Now, I want to see if this node exists in another xml. Is there a way by
which this can be achieved using XSLT ?


Sample Source XML : The dots are used as delimiters and will later be replaced to slashes in the XSLT.

Paths.xml

<Paths>
       <path1>books.book.author.name</path1>
       <path2>books.book.name</path2>
</Paths>

------------------------------------------------------------------------
-------------

Sample Input XML.

Input.xml

<books>
       <book>
               <name>a1</book>
               <price>10</price>
               <author>
                       <name>b1</name>
                       <gender>m</gender>
               </author>
       </book>
       <book>
               <name>a2</book>
               <price>10</price>
               <author>
                       <name>b2</name>
                       <gender>f</gender>
               </author>
       </book>
</books>


The XSLT should first get the path from the paths.xml and search the Input.xml to see if the node specified by the path exists. Can somebody please let me know how to go about solving this.

Regards,
BT


------------------------------------------------------------------------------ Notice: This e-mail message, together with any attachments, contains information of Merck & Co., Inc. (One Merck Drive, Whitehouse Station, New Jersey, USA 08889), and/or its affiliates (which may be known outside the United States as Merck Frosst, Merck Sharp & Dohme or MSD and in Japan, as Banyu - direct contact information for affiliates is available at http://www.merck.com/contact/contacts.html) that may be confidential, proprietary copyrighted and/or legally privileged. It is intended solely for the use of the individual or entity named on this message. If you are not the intended recipient, and have received this message in error, please notify us immediately by reply e-mail and then delete it from your system.


--
Regards,
Mukul Gandhi

Current Thread