0

Here is an excerpt from an xsl document (inside a template technically):

<table>
  <tr>
  <th>INSTANCE</th>
  <th>SWVER</th>
  <th>SYSTEMID</th>
  <th>SYSTIME</th>
  <th>SYSMEM</th>
  <th>CUTMEM</th>
  <th>FILEMEM</th>
  <th>CALCONFIG</th>
  </tr>
  <tr>
  <td><xsl:value-of select='@INSTANCE'/></td>
  <td><xsl:value-of select='@SWVER'/></td>
  <td><xsl:value-of select='@SYSTEMID'/></td>
  <td><xsl:value-of select='@SYSTIME'/></td>
  <td><xsl:value-of select='@SYSMEM'/></td>
  <td><xsl:value-of select='@CUTMEM'/></td>
  <td><xsl:value-of select='@FILEMEM'/></td>
  <td><xsl:value-of select="@CALCONFIG"/></td>
  </tr>
</table>

Is there some way that I can avoid the redundancy of writing out the attributes both as table headers and as the attribute selection? I cannot use external sources.

I was thinking I could define some xsl variable that contains a basic structure, as follows and generate the table from there.

<list>
  <item>INSTANCE</item>
  ...
  <item>CALCONFIG</item>
</list>

The XML data is just a bunch of tags, of the same value that contain at least the above listed attributes. Each tag looks something like this:

<THING INSTANCE="boop" SWVER="foo" SYSTEMID="123" 
...
CALCONFIG="cal.cfg" SOMETHINGELSE="bar"
/>
7
  • You need to show the input XML and the complete stylesheet. Commented Aug 25, 2016 at 1:54
  • Done. Got any ideas? Commented Aug 25, 2016 at 13:26
  • IMHO, the alternative will end up more verbose and less readable than what you have - exp. if you're using XSLT 1.0. Commented Aug 25, 2016 at 15:25
  • @michael.hor257k If there is some sort of alternative I'd still be quite interested. Thanks! Commented Aug 25, 2016 at 15:36
  • Which version of XSLT does your processor support? Commented Aug 25, 2016 at 15:39

2 Answers 2

2

To illustrate the point I made in a comment to your question, consider the following example:

XML

<root>
    <item color="red" name="alpha" size="small" garbage="123" id="1"/>
    <item color="green" name="bravo" size="medium" garbage="456" id="2"/>
    <item color="blue" name="charlie" size="large" garbage="789" id="3"/>
</root>

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="http://www.example.com/my"
exclude-result-prefixes="my">
<xsl:output method="html" encoding="utf-8"/>
<xsl:strip-space elements="*"/>

<my:columns>
    <col>id</col>
    <col>name</col>
    <col>size</col>
    <col>color</col>
</my:columns>
<xsl:variable name="columns" select="document('')/xsl:stylesheet/my:columns" />

<xsl:template match="/root">
    <table border="1">
        <tr>
            <xsl:for-each select="$columns/col">
                <th>
                    <xsl:value-of select="." />
                </th>
            </xsl:for-each>
        </tr>
        <xsl:for-each select="item">
            <xsl:variable name="attributes" select="@*" />
            <tr>
                <xsl:for-each select="$columns/col">
                    <td>
                        <xsl:value-of select="$attributes[name()=current()]" />
                    </td>
                </xsl:for-each>
            </tr>
        </xsl:for-each> 
    </table>
</xsl:template>

</xsl:stylesheet>

Result (rendered)

enter image description here

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks Michael, this is what I was looking for, even though it's less readable, it's probably going to save me some time.
One question, what does this line do? exclude-result-prefixes="my" I'm also curious as to why the namespace makes this work. Do you have anything you could point me to, or just explain here?
It prevents the namespace declaration xmlns:my="http://www.example.com/my"from appearing in the output. Any modern browser would ignore it anyway, so it's just a matter of good practice. -- The namespace is required, because without it columns would be interpreted as a literal result element and cause an error, since a literal result element cannot be outside of a template.
Thanks, another question though! How does this line work: <xsl:value-of select="$attributes[name()=current()]" I understand that attributes holds all the attributes for the item currently being evaluated and that we're basically looking up the attribute that matches the current column... but unless I'm missing something name() evaluates to col and current() evaluates to one of the column names. How would this line change if the column name were an attribute instead? e.g. <col name="id"/> instead of <col>id</col> Thanks!
The instruction selects from $attributes the attribute whose name is equal to the string-value of the current node. The current node is the current instance of col from $columns. If column name were an attribute, you'd have to say <xsl:value-of select="$attributes[name()=current()/@name()]. See: w3.org/TR/xpath/#predicates and :w3.org/TR/xslt/#misc-func
-1

Bryant, you need to work with two files (XML and XSL):

First, you need to specify a template (example.xsl):

<?xml version="1.0" encoding="UTF-8"?>

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

<xsl:template match="/">
  <html>
  <body>
  <h2>My Collection</h2>
  <table border="1">
    <tr bgcolor="#9acd32">
      <th>instance</th>
      <th>swver</th>
      <th>systemid</th>
      <th>systime</th>
      <th>sysmem</th>
      <th>cutmem</th>
      <th>filemem</th>
      <th>calconfig</th>
    </tr>
    <xsl:for-each select="catalog/cd">
    <tr>
      <td><xsl:value-of select="instance"/></td>
      <td><xsl:value-of select="swver"/></td>
      <td><xsl:value-of select="systemid"/></td>
      <td><xsl:value-of select="systime"/></td>
      <td><xsl:value-of select="sysmem"/></td>
      <td><xsl:value-of select="cutmem"/></td>
      <td><xsl:value-of select="filemem"/></td>
      <td><xsl:value-of select="calconfig"/></td>
    </tr>
    </xsl:for-each>
  </table>
  </body>
  </html>
</xsl:template>

</xsl:stylesheet>

And then you need to define your XML file (example.xml), based on the template (example.xsl):

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="example.xsl"?>
<catalog>
  <cd>
    <instance>instance1</instance>
    <swver>swver1</swver>
    <systemid>systemid1</systemid>
    <sysmem>sysmem1</sysmem>
    <systime>systime1</systime>
    <cutmem>cutmem1</cutmem>
    <filemem>filemem1</filemem>
    <calconfig>calconfig1</calconfig>

  </cd>
  <cd>
    <instance>instance2</instance>
    <swver>swver2</swver>
    <systemid>systemid2</systemid>
    <sysmem>sysmem2</sysmem>
    <systime>systime2</systime>
    <cutmem>cutmem2</cutmem>
    <filemem>filemem2</filemem>
    <calconfig>calconfig2</calconfig>

  </cd>
.
.
</catalog>

Result:

enter image description here

Reference: http://www.w3schools.com/xsl/xsl_transformation.asp

Hope this helps!

1 Comment

You didn't answer the question, just gave back what the OP has already said he's done. Please reread the question carefully.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.