简体   繁体   English

带有参数和输出值的调用模板-XSLT

[英]Call Template with Parameter and Output Value - XSLT

I have an 1 large xml file composed of 2 different xml files. 我有一个由2个不同的xml文件组成的1个大xml文件。 What I want to do is, when I create a CSV file, I want to be able to grab data from the second part of the file that matches the first part. 我想要做的是,当我创建CSV文件时,我希望能够从与第一部分匹配的文件的第二部分中获取数据。 I use a for each loop to go through all of the data in the first portion of the file, and then a nested loop to grab matching data. 我为每个循环使用a来遍历文件第一部分中的所有数据,然后使用嵌套循环来获取匹配的数据。 Here is the XML layout: 这是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>

What I would like in my CSV is to have the name from the Company_Data node inserted into the output right after the company_id. 我想在CSV文件中将Company_Data节点的名称插入到company_id之后的输出中。

Here is my XSL File (it currently does not work, it loops through and outputs N/A for each company data node in the output file): 这是我的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>

My output looks like this: 我的输出如下所示:

1, TestDept

Instead of: 代替:

1, Test1, TestDept

It is not outputting the value of the name node. 它不输出name节点的值。 How can I get it to display the value? 我怎样才能显示它的价值?

I can add stuff if more info is needed. 如果需要更多信息,我可以添加东西。

I cannot add a comment to ask for clarification on what you are expecting to output exactly, but some observations: 我无法添加评论以要求澄清您期望准确输出的内容,但有一些观察结果:

Currently your stylesheet will go through each company_id element, and for each one it finds it will loop through every Company_Data/Report_Entry element. 当前,您的样式表将遍历每个company_id元素,并且找到的每个样式表将遍历每个Company_Data / Report_Entry元素。 You are seeing N/A because for each company_id it checks every single Company_Data/Report_Entry, and is outputting N/A for any that don't match the current company_id. 您会看到N / A,因为它会为每个company_id检查每个单独的Company_Data / Report_Entry,并为与当前company_id不匹配的任何内容输出N / A。 To me it looks like you just need to remove the otherwise (in which case you wouldn't need a choose, just an if). 在我看来,您只需要删除else(在这种情况下,您无需选择,只需一个if)。 Note that when I tried running your stylesheet I was getting 001,Test1,N/A,,Test1,N/A, so slightly different to yours (but I had to add a missing for-each closing tag). 请注意,当我尝试运行样式表时,得到的是001,Test1,N / A ,, Test1,N / A,与您的略有不同(但是我必须添加一个缺少的for-each结束标记)。

In terms of the code and name elements, because you are in the for loop the focus has shifted to the element being looped on (Report_Data/Company_Data/Report_Entry) so you can use relative paths which will navigate from that looped element. 就代码和名称元素而言,由于您处于for循环中,因此焦点已转移到要循环的元素(Report_Data / Company_Data / Report_Entry),因此您可以使用将从该循环的元素导航的相对路径。 So you can just use "code" or "name". 因此,您可以只使用“代码”或“名称”。 You don't even need the "./" as this produces the same result. 您甚至不需要“ ./”,因为这会产生相同的结果。

You don't need to use an inner xsl:for-each loop here to look up the company name. 您无需在此处使用内部xsl:for-each循环来查找公司名称。 You could just use an xsl:variable here with a select parameter where you can put your 'contains' expressions 您可以在此处仅使用xsl:variable和select参数,在其中可以放置“包含”表达式

<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" />

Note the use of current() here, which is to ensure the expression uses the company_id of the current Report_Data/Report_Entry element you are on, as opposed to the Company_Data/Report_Entry you are searching in the expression. 请注意此处使用current() ,以确保表达式使用您正在使用的当前Report_Data / Report_Entry元素的company_id ,而不是您在表达式中搜索的Company_Data / Report_Entry If you were to do what you were currently doing, namely /Report_Data/Report_Entry/company_id , then this is an 'absolute' expression which starts from the top-level document node and will always return the first company_id in the XML. 如果要执行当前正在执行的操作,即/Report_Data/Report_Entry/company_id ,那么这是一个“绝对”表达式,它从顶级文档节点开始,并且始终会返回XML中的第一个company_id

But in anycase, you could then simply output this variable, or use an xsl:choose to output 'NA' instead should the variable be empty (ie No company name was found). 但是无论如何,您都可以简单地输出该变量,或者使用xsl:choose输出'NA'来代替,如果变量为空(即未找到公司名称)。

Were it not for the fact the ids do not match up, such looking up of values are usually better handled with a key. 不是因为id不匹配,通常使用键可以更好地处理值的查找。 To look up an Report_Entry by its code you would define a key like so 要通过其代码查找Report_Entry,您需要定义一个键,如下所示

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

Then to look it up you could do something like this... 然后要查找它,您可以执行以下操作...

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

Of course, this would fail in your case because the ids are not exactly the same, but perhaps you can just remove leading zeroes. 当然,在这种情况下这将失败,因为id并不完全相同,但是也许您可以删除前导零。 Try this, perhaps. 试试这个吧。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM