Re: [xsl] one line of xml to indented xml doc

Subject: Re: [xsl] one line of xml to indented xml doc
From: Peter Davis <pdavis152@xxxxxxxxx> (by way of Peter Davis <pdavis152@xxxxxxxxx>)
Date: Sun, 24 Mar 2002 13:32:12 -0800
Is indent="yes" not working?  It sounds like that should take care of it.  If
all you mean by "heirarchial structure" is "indent", then this might work:

<xsl:template match="node()">
  <xsl:param name="depth" select="0"/>
  <xsl:call-template name="indent">
    <xsl:with-param name="count" select="$depth"/>
  </xsl:call-template>
  <xsl:copy>
    <xsl:apply-templates select="@*"/>
    <xsl:text>&#10;</xsl:text>
    <xsl:apply-templates select="node()">
      <xsl:with-param name="depth" select="$depth + 1"/>
    </xsl:apply-templates>
  </xsl:copy>
</xsl:template>

<xsl:template match="@*">
  <xsl:copy/>
</xsl:template>

<xsl:template name="indent">
  <xsl:param name="count" select="0"/>
  <xsl:if test="$count > 0">
    <xsl:text>    </xsl:text>
    <xsl:call-template name="indent">
      <xsl:with-param name="count" select="$count - 1"/>
    </xsl:call-template>
  </xsl:if>
</xsl:template>

Each time a node() is matched, it gets the current depth of the node as a
param and calls a recursive "indent" template.  The indent template outputs
four spaces and then calls itself again and again until $count = 0, each time
subtracting 1 from count.

Then the main node() template copies all of the attributes (using
<xsl:copy-of select="@*"/> instead of the <xsl:apply-templates/> and another
"@*" template is an option).  It then outputs a newline character so that the
next node will show up on the next line.  Finally, calls itself on all of its
child nodes, which repeats the whole process, but this time with $depth + 1
so that the "indent" template will output one more set of spaces.

On Sunday 24 March 2002 12:32, Astor Rivera wrote:
> Thanks for the help, although I may not have explained what I really
> needed. You did point out some redundancy I found later that evening.
> What I was trying to transform is a single line of xml being output from a
> C++ app,
> I must then take it and make it a well formed document with a hierachical
> structure
> and the transform is being done using MSXSL.
>
> It must remain generic as the output tags will always vary.
>
> Here is what I have up to now,
>
> <?xml version="1.0"?>
> <xsl:stylesheet version="1.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
> <xsl:template match=" * | @* ">
> <xsl:copy>
>         <xsl:apply-templates select=" * | @* " />
> </xsl:copy>
> </xsl:template>
> </xsl:stylesheet>
>
> Although I am currently looking into using xsl:key to generate the
> hierarchical structure.
>
> Any more help is great.
>
> Thanks,
> Astor
>
>
>
> -----Original Message-----
> From: Peter Davis
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Sent: 3/24/02 2:26 AM
> Subject: Re: [xsl] one line of xml to indented xml doc
>
> On Friday 22 March 2002 15:52, Astor Rivera wrote:
> > This is what I have and would like to know how to indent the document.
> > The xml is coming from an application, and it's url encoded.
>
> So you have a source document that is not indented, and you want to
> indent
> it?  Well, if that's the case, then you have the right idea with
> <xsl:output
> indent="yes"/>.  The problem is that processors aren't required to
> support
> that; I know that Xalan doesn't do a very good job of it.  Saxon does,
> however.  Your milage will probably vary, though.
>
> BTW, your template has some very redundant parts:
> > <?xml version="1.0" encoding="UTF-8"?>
> > <xsl:stylesheet version="1.0"
> > xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
> > xmlns:fo="http://www.w3.org/1999/XSL/Format";>
> >         <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
> >         <xsl:template match=" * | node() | text() | @* ">
>
> "text()" and "*" are both redundant since they are matched by "node()".
> So
> really, the only thing you need here is <xsl:template match="node() |
> @*"/>.
>
> >                         <xsl:copy>
> >                                 <xsl:apply-templates  select=" * |
>
> node() |
>
> > @*"/>                            </xsl:copy>
>
> Same thing with your apply-templates.  "*" is taken care of by "node()",
> so
> all you need is <xsl:apply-templates select="@* | node()"/>.
>
> >         </xsl:template>
> > </xsl:stylesheet>
>
> Your question was a little confusing, so if this is not the answer you
> wanted
> you really should clarify what you mean by "indent".  I would also
> suggest
> re-indenting your stylesheet, because it's pretty ugly with the
> <xsl:copy>
> half way across the page :).  Or maybe that's where your having problems
> with
> indenting?  If so, please clarify.

--
Peter Davis
If you aren't rich you should always look useful.
		-- Louis-Ferdinand Celine

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread