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 August 10th, 2006, 09:52 AM
Registered User
 
Join Date: Jul 2006
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
Default Filtering XML data based on differnt XML

I am a beginner in XSLT.

I have an input XML file and a requiredelement.xml file which tells me the name of the elements that should be there in the output.

input.xml
<Root>
    <M1>
        <Element1>
            <Citizenship>aaaaaaaaa</Citizenship>
            <Phone a="b">phonenumber</Phone>
            <EmailAddress>email</EmailAddress>
        </Element1>
        <Element2>
            <Element2_2>Some data</Element2_2>
        </Element2>
        <Element3>data3</Element3>
        <Element4>data4</Element4>
        <Element5>data5</Element5>
        <Element6>data6</Element6>
        <Element7>data7</Element7>
        <Element8>data8</Element8>
        <Element9>data9</Element9>
    </M1>
</Root>

requiredelemnt.xml
<OutputElements>
        <segment>Element1</segment>
        <segment>Element6</segment>
</OutputElements>

The desired output
<Root>
    <M1>
        <Element1>
            <Citizenship>aaaaaaaaa</Citizenship>
            <Phone a="b">phonenumber</Phone>
            <EmailAddress>email</EmailAddress>
        </Element1>
        <Element6>data6</Element6>
    </M1>
</Root>


The XSL I am trying ( I know its wrong, but this as far as I can get )
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes">
    <xsl:template match="/">
        <xsl:for-each select="document('requiredelemnt.xml.xml')//segment">
            <xsl:apply-templates select=".">
                <xsl:with-param name="segvalue">
                    <xsl:value-of select="."/>
                </xsl:with-param>

            </xsl:apply-templates>
                        Here1
                </xsl:for-each>
    </xsl:template>
    <xsl:template match="segment">
        <xsl:param name="segvalue">localvalue</xsl:param>
        <xsl:copy-of select="$segvalue"/>
        Here 2 .. Value = <xsl:value-of select="$segvalue"/>
    </xsl:template>
</xsl:stylesheet>

The actual output that I am getting:
<?xml version="1.0" encoding="UTF-8"?>

        Here 2 .. Value = Element1
                        Here1


        Here 2 .. Value = Element6
                        Here1



Can you please help to correct or point me if I am totally off the mark.

Thanks
 
Old August 10th, 2006, 12:40 PM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

I would tackle this using two template rules: an identity copy rule that matches elements in the main document that are named in the second document, and a pass-through rule that matches elements not so named.

<xsl:template match="*[document('....')/x/y/z = name()]">
 <xsl:copy>
   <xsl:apply-templates/>
 </xsl:copy>
</xsl:template>

<xsl:template match="*">
  <xsl:apply-templates/>
</xsl:template>

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old August 10th, 2006, 04:22 PM
Registered User
 
Join Date: Jul 2006
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thanks a lot.. I could build my XSL based on your suggestions. I wanted the root element and its one subelement from the source and then filter based on my requiredelements.xml so here is the XSL
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes">
<xsl:output method="xml"/>
    <xsl:template match="/*|/*/*">
        <xsl:copy>
         <xsl:copy-of select="@*"/>
        <xsl:apply-templates mode="copy"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    <xsl:strip-space elements="*"/>
    <xsl:template match="*[document('v1.xml')//segment = name()] ">
        <xsl:copy>
            <xsl:copy-of select="@*|node()"/>
            <xsl:apply-templates mode="copy"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="*">
        <xsl:apply-templates/>
    </xsl:template>
</xsl:stylesheet>


 
Old August 11th, 2006, 08:06 AM
Registered User
 
Join Date: Jul 2006
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thanks Michael for your previous answer.
Just a small question. In the previous XSL, I am trying to do a case insensitive match by having the following XSL, but I get the error
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes">
<xsl:variable name="reqelm" select="document('v1.xml')"/>
<xsl:output method="xml"/>
    <xsl:template match="/*|/*/*">
        <xsl:copy>
         <xsl:copy-of select="@*"/>
        <xsl:apply-templates mode="copy"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    <xsl:strip-space elements="*"/>
<xsl:template match="*[lower-case($reqelm//segment)=lower-case(name())] ">
<xsl:copy>
            <xsl:copy-of select="@*|node()"/>
            <xsl:apply-templates mode="copy"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="*">
        <xsl:apply-templates/>
    </xsl:template>
</xsl:stylesheet>

The error is :
XPathParserException: The function 'lower-case' was not found.
pattern = '*[lower-case($reqelm//segment)=lower-case(name())] ' Remaining tokens are: ( 'lower-case' '(' '$' 'reqelm' '/' '/' 'segment' ')' '=' 'lower-case' '(' 'name' '(' ')' ')' ']') (t5.xsl, line 12, column 76)

I tried to replace the lower-case() with matches() but same problem.
 
Old August 11th, 2006, 08:12 AM
joefawcett's Avatar
Wrox Author
 
Join Date: Jun 2003
Posts: 3,074
Thanks: 1
Thanked 38 Times in 37 Posts
Default

Which processor are you using, very few support version 2.0, which lower-case() needs?
In version 1.0 you can use translate(string, from, to) and provide the appropriate alphabet strings for the last two parameters. This works with ASCII characters only though.

--

Joe (Microsoft MVP - XML)
 
Old August 11th, 2006, 09:15 AM
Registered User
 
Join Date: Jul 2006
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thanks Joe.
I am using Xalan version 1.10.0. so its not XSLT 2 I guess.

However when I tried to use translate in the match, I only get match on the first element
In the above example, I change the match line to
<xsl:template match="*[ translate($reqelm//segment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')=
    translate(name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')
    ] ">


I get the case insensitive match but only first element in ,my output. So the output I am getting now is
<Root>
    <M1>
        <Element1>
            <Citizenship>aaaaaaaaa</Citizenship>
            <Phone a="b">phonenumber</Phone>
            <EmailAddress>email</EmailAddress>
        </Element1>
    </M1>
</Root>
The expected output was
<Root>
    <M1>
        <Element1>
            <Citizenship>aaaaaaaaa</Citizenship>
            <Phone a="b">phonenumber</Phone>
            <EmailAddress>email</EmailAddress>
        </Element1>
        <Element6>data6</Element6>
    </M1>
</Root>

Any clue ?










Similar Threads
Thread Thread Starter Forum Replies Last Post
Filtering XML data aldwinenriquez XSLT 7 August 25th, 2008 03:24 AM
XML Filtering BlkR XML 1 June 12th, 2008 05:25 PM
Help with filtering xml jconroy XSLT 6 April 6th, 2008 11:33 PM
filtering xml in using XSLT venjamin XSLT 1 October 20th, 2006 04:21 AM
Filtering an xml with xslt Tomi XSLT 4 September 5th, 2006 06:29 AM





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