alortimor
alortimor

Reputation: 355

output nodes with for-each with xslt 1.0

Using the following xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:strip-space elements="*"/>

<xsl:template match="/all">
  <xsl:apply-templates select="linuxdirs/dir" />
</xsl:template>

<xsl:template match="dir[@runall='no']">
  <xsl:for-each select="sqlfile">
    <filename>
      <xsl:value-of select="@filename" />
      <xsl:text>&#10;</xsl:text>
    </filename>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

when I apply to the following xml:

<?xml version="1.0"?>
<?xml-stylesheet href="dirs.xsl" type="text/xsl"?>
<all>
  <topdir><dir td_id="1" dirname="./Database/APPS" owner="APPS" /></topdir>
  <linuxdirs>
    <dir td_id="1" did="1" dirname="./Database/APPS/DDL/Create/Tables" runall="no">
      <sqlfile f_id="1" filename="create_account_table.sql" />
    </dir>
    <dir td_id="1" did="2" dirname="./Database/APPS/DCL/Grant" runall="no">
      <sqlfile f_id="1" filename="xla_distribution_links.sql" />
      <sqlfile f_id="2" filename="grant_to_app_role.sql" />
    </dir>
    <dir td_id="1" did="3" dirname="./Database/APPS/DML/Insert" runall="yes"></dir>
  </linuxdirs>
</all>

I do not see all file names appear, only the last one ever appears, which for the above sample xml is xla_distribution_links.sql.

Can anybody suggest how to obtain the following output using xslt 1.0?

./Database/APPS/DDL/Create/Tables/create_account_table.sql
./Database/APPS/DCL/Grant/xla_distribution_links.sql
./Database/APPS/DCL/Grant/grant_to_app_role.sql

I am using xsltproc to parse xml on the command line.

I only get a single file name output using the code you've posted:

I still only get a single file output when using your code, although the format is now correct, so thanks for that, but why is it only showing a single file?

$ xsltproc -o out.csv dirs2.xsl dirs.xml
$ cat out.csv
./Database/APPS/DCL/Grant/xla_distribution_links.sql
$ cat dirs2.xsl
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:strip-space elements="*"/>

<xsl:template match="/all">
  <xsl:apply-templates select="linuxdirs/dir[@runall='no']" />
</xsl:template>

<xsl:template match="dir">
  <xsl:variable name="path" select="@dirname" />
    <xsl:for-each select="sqlfile">
    <filename>
      <xsl:value-of select="$path" />
      <xsl:text>/</xsl:text>
      <xsl:value-of select="@filename" />
      <xsl:text>&#10;</xsl:text>
    </filename>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>
$ cat dirs.xml
<?xml version="1.0"?>
<?xml-stylesheet href="dirs.xsl" type="text/xsl"?>
<all>
  <topdir><dir td_id="1" dirname="./Database/APPS" owner="APPS" /></topdir>
  <linuxdirs>
    <dir td_id="1" did="1" dirname="./Database/APPS/DDL/Create/Tables" runall="yes">
      <sqlfile f_id="1" filename="create_account_table.sql" />
    </dir>
    <dir td_id="1" did="2" dirname="./Database/APPS/DCL/Grant" runall="no">
      <sqlfile f_id="1" filename="xla_distribution_links.sql" />
    </dir>
    <dir td_id="1" did="3" dirname="./Database/APPS/DML/Insert" runall="no"></dir>
  </linuxdirs>
</all>

Upvotes: 0

Views: 89

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 117073

To get the result you show, you should do:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:strip-space elements="*"/>

<xsl:template match="/all">
  <xsl:apply-templates select="linuxdirs/dir[@runall='no']" />
</xsl:template>

<xsl:template match="dir">
    <xsl:variable name="path" select="@dirname" />
    <xsl:for-each select="sqlfile">
        <filename>
            <xsl:value-of select="$path" />
            <xsl:text>/</xsl:text>
            <xsl:value-of select="@filename" />
            <xsl:text>&#10;</xsl:text>
        </filename>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Note the predicate being moved from the match expression to xsl:apply-templates. The way you have it, templates are applied to all dir nodes, without exemption - and the built-in templates could produce unexpected results.

Upvotes: 1

Related Questions