带有for-each的输出节点xslt 1.0

时间:2016-05-16 11:08:44

标签: xslt-1.0

使用以下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>

当我申请以下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>

我没有看到所有文件名出现,只显示最后一个文件名,上面的示例xml是xla_distribution_links.sql。

有人可以建议如何使用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

我正在使用xsltproc在命令行上解析xml。

我只使用您发布的代码输出单个文件名:

我在使用你的代码时仍然只获得一个文件输出,虽然格式现在是正确的,所以多亏了,但为什么它只显示一个文件?

$ 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>

1 个答案:

答案 0 :(得分:1)

要获得您显示的结果,您应该:

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>

请注意谓词从匹配表达式移动到xsl:apply-templates。您拥有它的方式,模板应用于所有dir节点,无需豁免 - 内置模板可能会产生意外结果。