xsl-list
[Top] [All Lists]

Re: Finding wanted nodes in complex document

2002-10-11 13:31:07
Hi Geoff,

for such tasks it's better to use <xsl:template/> instead of <xsl:for-each/>. With templates it's easier to walk down the tree to different levels:

<xsl:template match="bookmarks">
  <bookmarks>
    <category>
      <xsl:apply-templates select="DT/H3"/>
      <xsl:apply-templates select="DL[DT/H3]"/>
    </category>
  </bookmarks>
</xsl:template>

<xsl:template match="DL">
  <subcat level="{count(ancestor::DL)}">
    <xsl:apply-templates select="DT/H3"/>
    <xsl:apply-templates select="DL[DT/H3]"/>
  </subcat>
</xsl:template>

<xsl:template match="H3">
  <xsl:attribute name="name">
    <xsl:value-of select="."/>
  </xsl:attribute>
</xsl:template>

I don't think that you get the expected output, but it should give you an idea how templates work.

I explained your error below ...

Geoff wrote:
I have a big,complicate, messy xml document (originally a Mozilla
bookmark file that I made into well-formed xml) that I wish to transform
into a lean, mean and clean xml document and I am having some trouble.


Here is part of the document:
<?xml version="1.0" encoding="UTF-8"?>
<bookmarks>
    <DT>
        <H3 ADD_DATE="1032875519" ID="NC:BookmarksRoot#$f68320c5"
            LAST_MODIFIED="1033072101">Consumer Guides</H3>
    </DT>
    <DL>
        <p/>
        <DT>
            <H3 ADD_DATE="1032876491"
ID="NC:BookmarksRoot#$f68320c6">Alabama</H3>
        </DT>
        <DL>
            <p/>
        </DL>
        <p/>
        <DT>
            <H3 ADD_DATE="1032876720" ID="NC:BookmarksRoot#$f68320dc"
LAST_MODIFIED="1033071828">Minnesota</H3>
        </DT>
        <DL>

What you are doing wrong? From your category <H3/> elements you always go up to the <DL> element above (first part '../../' of the XPath in <xsl:value-of/>). Now with the rest of the XPath you go down the tree to the first DL/DT/H3. And this is always the <H3>Mediation</H3> element.

Regards,

Joerg

            <p/>
            <DT>
                <H3 ADD_DATE="1033068848" ID="NC:BookmarksRoot#$c0ebfb0"
                    LAST_MODIFIED="1033077022">Alternative Dispute
Resolution</H3>
            </DT>
            <DL>
                <p/>
                <DT>
                    <H3 ADD_DATE="1032902327"
ID="NC:BookmarksRoot#$f6832141"
LAST_MODIFIED="1033077446">Mediation</H3>
                </DT>
                <DL>
                    <p/>
                    <DT>
                        <A ADD_DATE="1033077149"
HREF="http://www.co.hennepin.mn.us/courts/ConcCt/ccmediation.htm";
                            LAST_CHARSET="ISO-8859-1"
LAST_MODIFIED="1033077270">Mediation in
                            Conciliation Court [From the Hennepin County
District Court]</A>
                    </DT>
                </DL>
                <p/>
                <DT>
                    <A ADD_DATE="1033076751"
HREF="http://www.courts.state.mn.us/adr/adr_info.htm";
                        LAST_CHARSET="ISO-8859-1"
LAST_MODIFIED="1033076778">Minnesota Alternative
                        Dispute Resolution [From the Judicial
System]</A>
                </DT>
                <DT>
                    <A ADD_DATE="1033076913"
HREF="http://www.co.hennepin.mn.us/courts/Arbitration/arbmain.htm";
                        LAST_CHARSET="ISO-8859-1"
LAST_MODIFIED="1033076983"
                        LAST_VISIT="1033077513">What You Need to Know
About Arbitration [From the
                        Hennepin County District Court]</A>
                </DT>
            </DL>

<shortened/>

OK I told you it was messy.
So first I want to get all the "categories" which I do like this:

<xsl:for-each select="bookmarks/DL/DL/DT/H3">
        <category>
                <xsl:attribute name="name">
                        <xsl:value-of select="."/>
                </xsl:attribute>          
        </category>
</xsl:for-each>
This gives me a nice clean document like this:
  <category name="Alternative Dispute Resolution"/>
  <category name="Bankruptcy"/>
  <category name="Business Law"/>
  <category name="Charities"/>
  <category name="Civil Rights Law"/>
  <category name="Courts"/>
  <category name="Consumer Law"/>
  <category name="Contracts"/>
etc....
Now I want to get the "subcategories" related to the "categories" which
are at "bookmarks/DL/DL/DL/DT/H3" or "../../DL/DT/H3" when compared to
the "category" node.

So what I want is something like this:
<category name="Alternative Dispute Resolution">
        <subcat name="Mediation"/>
</category>
<category name="Bankruptcy"/>
<category name="Business Law">
        <subcat name="Corporations"/>
</category>

I am attempting to do this like this:
<xsl:for-each select="bookmarks/DL/DL/DT/H3">
        <category>
                <xsl:attribute name="name">
                        <xsl:value-of select="."/>
                </xsl:attribute>
                                
                <subcat>
                        <xsl:attribute name="name">
                                <xsl:value-of select="../../DL/DT/H3"/>
                        </xsl:attribute>
</subcat>
        </category>
</xsl:for-each>
But this produces this:
<category name="Alternative Dispute Resolution">
    <subcat name="Mediation"/>
</category>
<category name="Bankruptcy">
    <subcat name="Mediation"/>
</category>
<category name="Business Law">
    <subcat name="Mediation"/>
</category>
<category name="Charities">
    <subcat name="Mediation"/>
</category>

What am I doing wrong??


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



<Prev in Thread] Current Thread [Next in Thread>