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

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • ai2003lian@yahoo.com

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

    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=docu ment('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!

  • Joris Gillis

    #2
    Re: How to display all the ancestors and their attributes of a selected element?

    Tempore 23:06:17, die Thursday 10 February 2005 AD, hinc in foro {comp.text.xml} scripsit <ai2003lian@yah oo.com>:
    [color=blue]
    > <xsl:template match="node()|@ *">
    > <xsl:if test="(not(self ::Field )or
    > @FieldName=docu ment('requ­ire d.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:[/color]

    try something like:

    <xsl:template match="node()|@ *">
    <xsl:if test="not(self: :Field or self::Group)
    or (.|*)/@fieldName=docu ment('requ­ire d.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-v...i?userid=38041)
    Veni, vidi, wiki (http://www.wikipedia.org)

    Comment

    • ai2003lian@yahoo.com

      #3
      Re: How to display all the ancestors and their attributes of a selected element?

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

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



      </AllFields>

      Any ideas?


      Joris Gillis wrote:[color=blue]
      > Tempore 23:06:17, die Thursday 10 February 2005 AD, hinc in foro[/color]
      {comp.text.xml} scripsit <ai2003lian@yah oo.com>:[color=blue]
      >[color=green]
      > > <xsl:template match="node()|@ *">
      > > <xsl:if test="(not(self ::Field )or
      > > @FieldName=docu ment('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[/color][/color]
      all[color=blue][color=green]
      > > the empty lines and the last Group element:[/color]
      >
      > try something like:
      >
      > <xsl:template match="node()|@ *">
      > <xsl:if test="not(self: :Field or self::Group)
      > or (.|*)/@fieldName=docu ment('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[/color]
      when I try your template.[color=blue]
      >
      >
      > regards,
      > --
      > Joris Gillis[/color]
      (http://www.ticalc.org/cgi-bin/acct-v...i?userid=38041)[color=blue]
      > Veni, vidi, wiki (http://www.wikipedia.org)[/color]

      Comment

      • Joris Gillis

        #4
        Re: How to display all the ancestors and their attributes of a selected element?

        On 11 Feb 2005 07:19:08 -0800, <ai2003lian@yah oo.com> wrote:
        [color=blue]
        > Thank. But it didn't work. The result xml is as the following:
        >
        > <?xml version="1.0"?>
        > <AllFields>
        >
        >
        >
        > </AllFields>
        >
        > Any ideas?
        >[/color]

        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:styleshe et version="1.0"
        xmlns:xsl="http ://www.w3.org/1999/XSL/Transform">

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

        <xsl:template match="node()|@ *">
        <xsl:if test="not(self: :Field or self::Group)
        or (.|*)/@fieldName=docu ment('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/

        Comment

        • ai2003lian@yahoo.com

          #5
          Re: How to display all the ancestors and their attributes of a selected element?

          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:output method = "xml" indent = "yes" />

          <xsl:template match="node()">
          <xsl:if
          test="descendan t-or-self::*/@fieldName=docu ment('required. xml')/*/FieldName
          or @FieldName=docu ment('requ­ired .xml')/*/FieldName">
          <xsl:text>
          </xsl:text>
          <xsl:element name = "{name(self::*) }" >
          <xsl:for-each select = "@*" >
          <xsl:attribut e name="{name(cur rent())}" >
          <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:[color=blue]
          > On 11 Feb 2005 07:19:08 -0800, <ai2003lian@yah oo.com> wrote:
          >[color=green]
          > > Thank. But it didn't work. The result xml is as the following:
          > >
          > > <?xml version="1.0"?>
          > > <AllFields>
          > >
          > >
          > >
          > > </AllFields>
          > >
          > > Any ideas?
          > >[/color]
          >
          > 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:styleshe et version="1.0"
          > xmlns:xsl="http ://www.w3.org/1999/XSL/Transform">
          >
          > <xsl:strip-space elements="*"/>
          > <xsl:output method="xml" indent="yes"/>
          >
          > <xsl:template match="node()|@ *">
          > <xsl:if test="not(self: :Field or self::Group)
          > or (.|*)/@fieldName=docu ment('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[/color]
          the[color=blue]
          > 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[/color]
          probably[color=blue]
          > some wrong names in the test expression that cause the trouble with[/color]
          your[color=blue]
          > real XML.
          >
          > --
          > Using Opera's revolutionary e-mail client: http://www.opera.com/m2/[/color]

          Comment

          • Joris Gillis

            #6
            Re: How to display all the ancestors and their attributes of a selected element?

            On 11 Feb 2005 09:49:02 -0800, <ai2003lian@yah oo.com> wrote:
            [color=blue]
            > 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:output method = "xml" indent = "yes" />
            >
            > <xsl:template match="node()">
            > <xsl:if
            > test="descendan t-or-self::*/@fieldName=docu ment('required. xml')/*/FieldName
            > or @FieldName=docu ment('requ­ired .xml')/*/FieldName">
            > <xsl:text>
            > </xsl:text>
            > <xsl:element name = "{name(self::*) }" >
            > <xsl:for-each select = "@*" >
            > <xsl:attribut e name="{name(cur rent())}" >
            > <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.[/color]

            how about this template?

            <xsl:template match="node()">
            <xsl:if
            test="descendan t-or-self::*/@fieldName=docu ment('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/

            Comment

            • ai2003lian@yahoo.com

              #7
              Re: How to display all the ancestors and their attributes of a selected element?

              It did the trick! Thanks!

              Comment

              Working...