1
votes

I'm writing generic xsl stylesheet for previewing xml in the system, it mostly works fine, but for some cases it skips span.label and span.value from markup.

So for istance if there is tag having children with just text - it works. (a > b+c)

If there is just tag with text on first level, it will only output text content omitting tag name. ( a )

Also if there are tag that has one child which has several children with text - it will omit first level tag name, show second level tag name and show only text content for third level. ( a > b > c + d + e)

Here is xslt:

<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/">
    <html>
    <head>
    <title>Preview</title>
    <meta charset="utf-8" />    
    <style>
              .level { line-heigth: 20px; }
              .label { width: 150px; display:inline-block; 
                       background-color:#eee; margin-right:10px; 
                       margin-top:5px; padding:5px; vertical-align:top; }
              .value { display:inline-block;  vertical-align:top; 
                       padding: 5px; margin-top:5px;}               
    </style>
    </head>
    <body>
        <div class='level'>
                <xsl:apply-templates /> 
            </div>  
    </body>
    </html>
    </xsl:template>

    <xsl:template match="*" >  
        <span class='label'><xsl:value-of select ="local-name(.)"/><xslt:text>:</xslt:text></span>
        <span class='value'><xsl:value-of select="text()" /></span>
        <xsl:if test="attribute::*">
        <br />
        <span class="label"> attributes: 
                       <xsl:number value="count(attribute::*)" format="1"/></span>
        <span class="value">
                      <xsl:for-each select="attribute::*">   
            <xsl:value-of select="local-name()" />
                        <xslt:text> : </xslt:text>
                        <xsl:value-of select="." />   
          </xsl:for-each>
         </span>
         </xsl:if>
        <xsl:for-each select="*">
            <div class='level'>
               <xsl:apply-templates />
            </div>
        </xsl:for-each>
        <br />
    </xsl:template>
</xsl:stylesheet>
1

1 Answers

1
votes

It's hard to say without sample input/output, but I think the issue is here:

    <xsl:for-each select="*">
        <div class='level'>
           <xsl:apply-templates />
        </div>
    </xsl:for-each>

You're looping over each child element (select="*") and not outputting any information about it.

Try removing the xsl:for-each and just doing an <xsl:apply-templates select="*"/>. You'll have to move the div too.

Maybe something like:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="/">
        <html>
            <head>
                <title>Preview</title>
                <meta charset="utf-8" />    
                <style>
                    .level { line-heigth: 20px; }
                    .label { width: 150px; display:inline-block; 
                    background-color:#eee; margin-right:10px; 
                    margin-top:5px; padding:5px; vertical-align:top; }
                    .value { display:inline-block;  vertical-align:top; 
                    padding: 5px; margin-top:5px;}               
                </style>
            </head>
            <body>
                <xsl:apply-templates /> 
            </body>
        </html>
    </xsl:template>

    <xsl:template match="*" >  
        <div class='level'>
            <span class='label'><xsl:value-of select ="local-name(.)"/><xsl:text>:</xsl:text></span>
            <span class='value'><xsl:value-of select="text()" /></span>
            <xsl:if test="@*">
                <br />
                <span class="label"> attributes: 
                        <xsl:number value="count(@*)" format="1"/></span>
                <span class="value">
                    <xsl:for-each select="@*">   
                        <xsl:value-of select="local-name()" />
                        <xsl:text> : </xsl:text>
                        <xsl:value-of select="." />   
                    </xsl:for-each>
                </span>
            </xsl:if>
            <br />
            <xsl:apply-templates select="*"/>
        </div>
    </xsl:template>
</xsl:stylesheet>

(I also replaced all attribute:: axes with the abbreviated syntax @.)