使用参数和输出值调用模板 - XSLT

时间:2013-11-26 14:47:07

标签: xml xslt csv

我有一个由2个不同的xml文件组成的1个大型xml文件。 我想要做的是,当我创建一个CSV文件时,我希望能够从文件的第二部分中获取与第一部分匹配的数据。 我使用a for each循环遍历文件第一部分中的所有数据,然后使用嵌套循环来获取匹配数据。 这是XML布局:

<?xml version="1.0" encoding="UTF-8"?>
<Report_Data>
    <Report_Entry>
        <company_id>001</company_id>
        <dept>TestDept</dept>
    </Report_Entry>
    <Report_Entry>
    </Report_Entry>
    <Company_Data>
        <Report_Entry>
            <code>1</code>
            <name>Test1</name>
        </Report_Entry>
        <Report_Entry>
            <code>2</code>
            <name>Test2</name>
        </Report_Entry>
    </Company_Data>
</Report_Data>

我想在CSV中使用的是将Company_Data节点中的名称插入到company_id之后的输出中。

这是我的XSL文件(它当前不起作用,它循环并输出输出文件中每个公司数据节点的N / A):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wd="urn:com.workday/bsvc">
<xsl:output method="text" encoding="utf-8" media-type="text/plain" />
<xsl:strip-space  elements="*"/>

<xsl:variable name="newline" select="'&#x0A;'" />
<xsl:variable name="tab" select="'&#x09;'" />
<xsl:variable name="comma" select="'&#x2C;'" />
<xsl:variable name="padding" select="'                              '" />

<xsl:variable name="ID" select="concat('COMPANY ID', $padding)" />
<xsl:variable name="NAME" select="concat('COMPANY NAME', $padding)" />
<xsl:variable name="DEPT" select="concat('DEPARTMENT', $padding)" />

<xsl:template match="/">
    <xsl:value-of select="$ID"/><xsl:value-of select="$comma"/>
    <xsl:value-of select="$NAME"/><xsl:value-of select="$comma"/>
    <xsl:value-of select="$DEPT"/><xsl:value-of select="$comma"/>

    <xsl:for-each select="/Report_Data/Report_Entry">
    <xsl:value-of select="translate(substring(concat(company_id, $padding), 1, string-length($ID)), ',', ' ')" /><xsl:value-of select="$comma"/>

    <xsl:call-template name="company_name">
        <xsl:with-param name="id_number" select="company_id"></xsl:with-param>
</xsl:call-template>

    <xsl:value-of select="translate(substring(concat(dept, $padding), 1, string-length($DEPT)), ',', ' ')" /><xsl:value-of select="$comma"/>
</xsl:for-each>

</xsl:template>

<xsl:template name="company_name" match="/wd:Report_Data/wd:Company_Data">
<xsl:param name="id_number"></xsl:param>
<xsl:for-each select="/wd:Report_Entry">
    <xsl:if test="contains($id_number, code)">
        <xsl:value-of select="/name/text()"/>
    </xsl:if>
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>

我的输出如下:

1, TestDept

而不是:

1, Test1, TestDept

它不输出name节点的值。 如何让它显示值?

如果需要更多信息,我可以添加内容。

2 个答案:

答案 0 :(得分:1)

我无法添加评论来要求澄清您期望输出的内容,但有些意见:

目前,您的样式表将遍历每个company_id元素,对于每个找到它,它将遍历每个Company_Data / Report_Entry元素。 您看到N / A,因为对于每个company_id,它会检查每个Company_Data / Report_Entry,并为任何与当前company_id不匹配的任何内容输出N / A. 对我来说,看起来你只需要删除其他(在这种情况下你不需要选择,只需一个if)。 请注意,当我尝试运行样式表时,我得到的是001,Test1,N / A,Test1,N / A,与您的稍有不同(但我必须为每个结束标记添加一个缺失的内容)。

就代码和名称元素而言,因为您处于for循环中,焦点已转移到循环播放的元素(Report_Data / Company_Data / Report_Entry),因此您可以使用将从该循环元素导航的相对路径。 所以你可以使用“代码”或“名称”。你甚至不需要“./”,因为这会产生相同的结果。

答案 1 :(得分:1)

您无需在此处使用内部 xsl:for-each 循环来查找公司名称。你可以在这里使用 xsl:variable 和一个select参数来放置你的'contains'表达式

<xsl:for-each select="Report_Data/Report_Entry">
    <xsl:variable 
         name="company_name" 
         select="/Report_Data/Company_Data/Report_Entry[contains(current()/company_id, code)]/name" />

请注意这里使用 current(),这是为了确保表达式使用当前 Report_Data / Report_Entry 元素的 company_id 已打开,而不是您在表达式中搜索的 Company_Data / Report_Entry 。如果您要执行当前正在执行的操作,即/Report_Data/Report_Entry/company_id,那么这是一个“绝对”表达式,它从顶级文档节点开始,并始终返回第一个 company_id XML。

但无论如何,你可以简单地输出这个变量,或者使用 xsl:choose 来输出'NA'而不是变量是空的(即没有找到公司名称)。

如果不是因为id不匹配,那么查找值通常可以通过密钥更好地处理。要通过代码查找Report_Entry,您可以定义一个类似

的键
<xsl:key name="company" match="Company_Data/Report_Entry" use="code" />

然后查找它你可以做这样的事情......

<xsl:for-each select="Report_Data/Report_Entry">
    <xsl:variable name="company_name" select="key('company', company_id)" />

当然,在你的情况下这会失败,因为id不完全相同,但也许你可以删除前导零。也许尝试这个。

<xsl:for-each select="Report_Data/Report_Entry">
    <xsl:variable name="company_name" select="key('company', number(company_id))" />