How to display all the ancestors and their attributes of a selected element?

Discussion in 'XML' started by ai2003lian@yahoo.com, Feb 10, 2005.

  1. Guest

    Assuming I have the following two xml file:


    source.xml:

    <AllFields>
    <Group name="G1">
    <Field fieldName="f1">Value1</Field>
    <Field fieldName="f2">Value2</Field>
    <Field fieldName="f3">Value3</Field>
    </Group>
    <Group name="G2">
    <Field fieldName="f4">Value4</Field>
    <Field fieldName="f5">Value5</Field>
    <Field fieldName="f6">Value6</Field>
    </Group>
    <Group name="G3">
    <Field fieldName="f7">Value7</Field>
    <Field fieldName="f8">Value8</Field>
    <Field fieldName="f9">Value9</Field>
    </Group>
    </AllFields>

    requ­ired.xml:

    <RequiredFields>
    <FieldName>f1</FieldName>
    <FieldName>f3</FieldName>
    <FieldName>f6</FieldName>
    </RequiredFields>


    The requirement.xml defines which field will go to the output XML.

    The xsl file and output XML are like the following:

    xsl file:

    <xsl:template match="node()|@*">
    <xsl:if test="(not(self::Field )or
    @FieldName=document('requ­ired.xml')/*/FieldName">
    <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
    </xsl:if>
    </xsl:template>

    output.xml

    <AllFields>
    <Group name="G1">
    <Field fieldName="f1">Value1</Field>

    <Field fieldName="f3">Value3</Field>
    </Group>
    <Group name="G2">


    <Field fieldName="f6">Value6</Field>
    </Group>
    <Group name="G3">



    </Group>
    </AllFields>


    How could I use XSLT to get the following desired output(without all
    the empty lines and the last Group element:


    <AllFields>
    <Group name="G1">
    <Field fieldName="f1">Value1</Field>
    <Field fieldName="f3">Value3</Field>
    </Group>
    <Group name="G2">
    <Field fieldName="f6">Value6</Field>
    </Group>
    </AllFields>


    Thanks your help in advance!
     
    , Feb 10, 2005
    #1
    1. Advertising

  2. Joris Gillis Guest

    Tempore 23:06:17, die Thursday 10 February 2005 AD, hinc in foro {comp.text.xml} scripsit <>:

    > <xsl:template match="node()|@*">
    > <xsl:if test="(not(self::Field )or
    > @FieldName=document('requ­ired.xml')/*/FieldName">
    > <xsl:copy>
    > <xsl:apply-templates select="node()|@*"/>
    > </xsl:copy>
    > </xsl:if>
    > </xsl:template>
    >
    > How could I use XSLT to get the following desired output(without all
    > the empty lines and the last Group element:


    try something like:

    <xsl:template match="node()|@*">
    <xsl:if test="not(self::Field or self::Group)
    or (.|*)/@fieldName=document('requ­ired.xml')/*/FieldName">
    <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
    </xsl:if>
    </xsl:template>

    (do beware of lower/uppercase, when you're testing this)

    As for the whitespaces in your output, I don't see them occurring when I try your template.


    regards,
    --
    Joris Gillis (http://www.ticalc.org/cgi-bin/acct-view.cgi?userid=38041)
    Veni, vidi, wiki (http://www.wikipedia.org)
     
    Joris Gillis, Feb 11, 2005
    #2
    1. Advertising

  3. Guest

    Thank. But it didn't work. The result xml is as the following:

    <?xml version="1.0"?>
    <AllFields>



    </AllFields>

    Any ideas?


    Joris Gillis wrote:
    > Tempore 23:06:17, die Thursday 10 February 2005 AD, hinc in foro

    {comp.text.xml} scripsit <>:
    >
    > > <xsl:template match="node()|@*">
    > > <xsl:if test="(not(self::Field )or
    > > @FieldName=document('requ­ired.xml')/*/FieldName">
    > > <xsl:copy>
    > > <xsl:apply-templates select="node()|@*"/>
    > > </xsl:copy>
    > > </xsl:if>
    > > </xsl:template>
    > >
    > > How could I use XSLT to get the following desired output(without

    all
    > > the empty lines and the last Group element:

    >
    > try something like:
    >
    > <xsl:template match="node()|@*">
    > <xsl:if test="not(self::Field or self::Group)
    > or (.|*)/@fieldName=document('requ­ired.xml')/*/FieldName">
    > <xsl:copy>
    > <xsl:apply-templates select="node()|@*"/>
    > </xsl:copy>
    > </xsl:if>
    > </xsl:template>
    >
    > (do beware of lower/uppercase, when you're testing this)
    >
    > As for the whitespaces in your output, I don't see them occurring

    when I try your template.
    >
    >
    > regards,
    > --
    > Joris Gillis

    (http://www.ticalc.org/cgi-bin/acct-view.cgi?userid=38041)
    > Veni, vidi, wiki (http://www.wikipedia.org)
     
    , Feb 11, 2005
    #3
  4. Joris Gillis Guest

    On 11 Feb 2005 07:19:08 -0800, <> wrote:

    > Thank. But it didn't work. The result xml is as the following:
    >
    > <?xml version="1.0"?>
    > <AllFields>
    >
    >
    >
    > </AllFields>
    >
    > Any ideas?
    >


    Very strange...

    Tested with Saxon and AltovaXSLT

    input:
    <AllFields>
    <Group name="G1">
    <Field fieldName="f1">Value1</Field>
    <Field fieldName="f2">Value2</Field>
    <Field fieldName="f3">Value3</Field>
    </Group>
    <Group name="G2">
    <Field fieldName="f4">Value4</Field>
    <Field fieldName="f5">Value5</Field>
    <Field fieldName="f6">Value6</Field>
    </Group>
    <Group name="G3">
    <Field fieldName="f7">Value7</Field>
    <Field fieldName="f8">Value8</Field>
    <Field fieldName="f9">Value9</Field>
    </Group>
    </AllFields>

    required.xml:
    <RequiredFields>
    <FieldName>f1</FieldName>
    <FieldName>f3</FieldName>
    <FieldName>f6</FieldName>
    </RequiredFields>

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

    <xsl:strip-space elements="*"/>
    <xsl:eek:utput method="xml" indent="yes"/>

    <xsl:template match="node()|@*">
    <xsl:if test="not(self::Field or self::Group)
    or (.|*)/@fieldName=document('required.xml')/*/FieldName">
    <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
    </xsl:if>
    </xsl:template>

    </xsl:stylesheet>

    (notice the 'strip-space' element I added; it solves the issue with the
    linebreaks.

    output:

    <AllFields>
    <Group name="G1">
    <Field fieldName="f1">Value1</Field>
    <Field fieldName="f3">Value3</Field>
    </Group>
    <Group name="G2">
    <Field fieldName="f6">Value6</Field>
    </Group>
    </AllFields>


    The stylesheet probably needed adaption to your real XML. It's probably
    some wrong names in the test expression that cause the trouble with your
    real XML.

    --
    Using Opera's revolutionary e-mail client: http://www.opera.com/m2/
     
    Joris Gillis, Feb 11, 2005
    #4
  5. Guest

    Thanks. It still didn't work for me since I'm using XML C parser
    libxml2 and libxslt. But I came up with the following solution:

    <xsl:eek:utput method = "xml" indent = "yes" />

    <xsl:template match="node()">
    <xsl:if
    test="descendant-or-self::*/@fieldName=document('required.xml')/*/FieldName
    or @FieldName=document('requ­ired.xml')/*/FieldName">
    <xsl:text>
    </xsl:text>
    <xsl:element name = "{name(self::*)}" >
    <xsl:for-each select = "@*" >
    <xsl:attribute name="{name(current())}" >
    <xsl:value-of select = "current()" />
    </xsl:attribute>
    </xsl:for-each>
    <xsl:apply-templates select="node()"/>
    <xsl:value-of select = "node()" />
    </xsl:element>
    </xsl:if>
    </xsl:template>
    </xsl:stylesheet>

    It works fine although I'm still looking for a better way to do it.


    Joris Gillis wrote:
    > On 11 Feb 2005 07:19:08 -0800, <> wrote:
    >
    > > Thank. But it didn't work. The result xml is as the following:
    > >
    > > <?xml version="1.0"?>
    > > <AllFields>
    > >
    > >
    > >
    > > </AllFields>
    > >
    > > Any ideas?
    > >

    >
    > Very strange...
    >
    > Tested with Saxon and AltovaXSLT
    >
    > input:
    > <AllFields>
    > <Group name="G1">
    > <Field fieldName="f1">Value1</Field>
    > <Field fieldName="f2">Value2</Field>
    > <Field fieldName="f3">Value3</Field>
    > </Group>
    > <Group name="G2">
    > <Field fieldName="f4">Value4</Field>
    > <Field fieldName="f5">Value5</Field>
    > <Field fieldName="f6">Value6</Field>
    > </Group>
    > <Group name="G3">
    > <Field fieldName="f7">Value7</Field>
    > <Field fieldName="f8">Value8</Field>
    > <Field fieldName="f9">Value9</Field>
    > </Group>
    > </AllFields>
    >
    > required.xml:
    > <RequiredFields>
    > <FieldName>f1</FieldName>
    > <FieldName>f3</FieldName>
    > <FieldName>f6</FieldName>
    > </RequiredFields>
    >
    > XSL:
    > <xsl:stylesheet version="1.0"
    > xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    >
    > <xsl:strip-space elements="*"/>
    > <xsl:eek:utput method="xml" indent="yes"/>
    >
    > <xsl:template match="node()|@*">
    > <xsl:if test="not(self::Field or self::Group)
    > or (.|*)/@fieldName=document('required.xml')/*/FieldName">
    > <xsl:copy>
    > <xsl:apply-templates select="node()|@*"/>
    > </xsl:copy>
    > </xsl:if>
    > </xsl:template>
    >
    > </xsl:stylesheet>
    >
    > (notice the 'strip-space' element I added; it solves the issue with

    the
    > linebreaks.
    >
    > output:
    >
    > <AllFields>
    > <Group name="G1">
    > <Field fieldName="f1">Value1</Field>
    > <Field fieldName="f3">Value3</Field>
    > </Group>
    > <Group name="G2">
    > <Field fieldName="f6">Value6</Field>
    > </Group>
    > </AllFields>
    >
    >
    > The stylesheet probably needed adaption to your real XML. It's

    probably
    > some wrong names in the test expression that cause the trouble with

    your
    > real XML.
    >
    > --
    > Using Opera's revolutionary e-mail client: http://www.opera.com/m2/
     
    , Feb 11, 2005
    #5
  6. Joris Gillis Guest

    On 11 Feb 2005 09:49:02 -0800, <> wrote:

    > Thanks. It still didn't work for me since I'm using XML C parser
    > libxml2 and libxslt. But I came up with the following solution:
    >
    > <xsl:eek:utput method = "xml" indent = "yes" />
    >
    > <xsl:template match="node()">
    > <xsl:if
    > test="descendant-or-self::*/@fieldName=document('required.xml')/*/FieldName
    > or @FieldName=document('requ­ired.xml')/*/FieldName">
    > <xsl:text>
    > </xsl:text>
    > <xsl:element name = "{name(self::*)}" >
    > <xsl:for-each select = "@*" >
    > <xsl:attribute name="{name(current())}" >
    > <xsl:value-of select = "current()" />
    > </xsl:attribute>
    > </xsl:for-each>
    > <xsl:apply-templates select="node()"/>
    > <xsl:value-of select = "node()" />
    > </xsl:element>
    > </xsl:if>
    > </xsl:template>
    > </xsl:stylesheet>
    >
    > It works fine although I'm still looking for a better way to do it.


    how about this template?

    <xsl:template match="node()">
    <xsl:if
    test="descendant-or-self::*/@fieldName=document('required.xml')/*/FieldName">
    <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:apply-templates select="node()"/>
    <xsl:value-of select="text()" />
    </xsl:copy>
    </xsl:if>
    </xsl:template>

    (correct result in Saxon), just curious to know if your processor can
    handle this...

    --
    Using Opera's revolutionary e-mail client: http://www.opera.com/m2/
     
    Joris Gillis, Feb 11, 2005
    #6
  7. Guest

    It did the trick! Thanks!
     
    , Feb 11, 2005
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. yurick

    XML: Collecting ancestors

    yurick, Jan 14, 2004, in forum: XML
    Replies:
    2
    Views:
    532
    yurick
    Jan 15, 2004
  2. Martin Pettersson

    Multiply ancestors in xsl

    Martin Pettersson, Oct 5, 2004, in forum: XML
    Replies:
    2
    Views:
    2,114
    Martin Pettersson
    Oct 18, 2004
  3. Replies:
    2
    Views:
    384
  4. Replies:
    3
    Views:
    180
  5. Yanick

    JQuery and ancestors

    Yanick, Dec 30, 2006, in forum: Javascript
    Replies:
    4
    Views:
    109
    Yanick
    Dec 31, 2006
Loading...

Share This Page