草庐IT

xml - 在 xslt 模板中创建 key

coder 2024-07-01 原文

我想将 XML 文件转换为 CSV 文件。我要导出的字段是 <issues> .每个问题都有一组标准字段和一些自定义字段。可能的自定义字段在 <issue-custom-fields> 中定义.不是每个 <issue>已设置所有自定义字段。对于 CSV 导出,我必须为每个缺失的条目添加一个空字段 ( ",," )。我该怎么做?

以下 xslt 文件循环遍历所有问题字段和所有自定义字段。而不是“字段值”?我想在当前项目中查找相应的字段值(如果存在,则为空白)。

XSLT 版本应为 1.0。

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

    <xsl:output method="text" />

    <xsl:template match="/">
        <xsl:apply-templates select="xml_data/issues"/>
    </xsl:template>

    <xsl:template match="issue">
        <xsl:for-each select="*">
            <xsl:choose>
                <xsl:when test="name(.) = 'custom-values'">
                    <xsl:for-each select="/xml_data/issue-custom-fields/issue-custom-field">                                
                        <xsl:variable name="f" select="id" />

                        <xsl:text>field value?</xsl:text>

                        <xsl:if test="position() != last()">
                            <xsl:text>,</xsl:text>
                        </xsl:if>
                    </xsl:for-each>
                </xsl:when>

                <xsl:otherwise>
                    <xsl:value-of select="."/>          
                    <xsl:if test="position() != last()">
                        <xsl:text>,</xsl:text>
                    </xsl:if>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>         
    </xsl:template>
</xsl:transform>

作用于以下数据:

<?xml version="1.0" encoding="UTF-8"?>
    <xml_data>
        <projects type="array">
            <project>
                <id type="integer">10</id>
                <name>Helpdesk</name>
                <type>open</type>
            </project>
            <project>
                <id type="integer">20</id>
                <name>Development</name>
                <type>closed</type>
            </project>
        </projects>

        <issue-custom-fields>
            <issue-custom-field>
                <id>1000</id>
                <name>Delay</name>
            </issue-custom-field>
            <issue-custom-field>
                <id>1001</id>
                <name>Means of Delivery</name>
            </issue-custom-field>
            <issue-custom-field>
                <id>1002</id>
                <name>Shipping Date</name>
            </issue-custom-field>
        </issue-custom-fields>

        <issues type="array">
            <issue>
                <id type="integer">100</id>
                <project-id type="integer">10</project-id>
                <subject>first helpdesk issue</subject>
                <description>a small problem</description>
                <custom-values>
                    <custom-value>
                        <custom-field-id>1000</custom-field-id>
                        <value>15</value>
                    </custom-value>
                    <custom-value>
                        <custom-field-id>1002</custom-field-id>
                        <value>2016-08-01</value>
                    </custom-value>
                </custom-values>
            </issue>
            <issue>
                <id type="integer">101</id>
                <project-id type="integer">10</project-id>
                <subject>second helpdesk issue</subject>
                <description>a medium problem</description>
                <custom-values>
                    <custom-value>
                        <custom-field-id>1000</custom-field-id>
                        <value>10</value>
                    </custom-value>
                    <custom-value>
                        <custom-field-id>1001</custom-field-id>
                        <value>FTP</value>
                    </custom-value>
                </custom-values>
            </issue>
            <issue>
                <id type="integer">102</id>
                <project-id type="integer">10</project-id>
                <subject>third helpdesk issue</subject>
                <description>a huge security problem</description>
                <custom-values>
                    <custom-value>
                        <custom-field-id>1001</custom-field-id>
                        <value>SSH</value>
                    </custom-value>
                </custom-values>
            </issue>
            <issue>
                <id type="integer">103</id>
                <project-id type="integer">20</project-id>
                <subject>first "development" issue</subject>
                <description>just some "strange" software</description>
                <custom-values>
                </custom-values>
            </issue>
        </issues>
    </xml_data>

非常感谢您的帮助。

最佳答案

如果我没理解错的话,你想做的是:

XSLT 1.0

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

<xsl:key name="custom-value" match="custom-value" use="concat(custom-field-id, '|', ancestor::issue/id)" />

<xsl:template match="/xml_data">
    <xsl:variable name="custom-fields" select="issue-custom-fields/issue-custom-field" />
    <!-- header -->
    <!-- standard fields -->
    <xsl:for-each select="issues/issue[1]/*[not(self::custom-values)]">
        <xsl:value-of select="name()"/>          
        <xsl:text>,</xsl:text>
    </xsl:for-each> 
    <!-- custom fields -->
    <xsl:for-each select="$custom-fields">
        <xsl:value-of select="name"/>          
        <xsl:if test="position() != last()">
            <xsl:text>,</xsl:text>
        </xsl:if>
    </xsl:for-each>
    <xsl:text>&#10;</xsl:text>
    <!-- data -->
    <xsl:for-each select="issues/issue">
        <xsl:variable name="issue-id" select="id" />
        <!-- standard fields -->
        <xsl:for-each select="*[not(self::custom-values)]">
            <xsl:value-of select="."/>          
            <xsl:text>,</xsl:text>
        </xsl:for-each>
        <!-- custom fields -->
        <xsl:for-each select="$custom-fields">
            <xsl:value-of select="key('custom-value', concat(id, '|', $issue-id))/value"/>          
            <xsl:if test="position() != last()">
                <xsl:text>,</xsl:text>
            </xsl:if>
        </xsl:for-each> 
        <xsl:text>&#10;</xsl:text>
    </xsl:for-each> 
</xsl:template>

</xsl:stylesheet>

应用于您的输入示例,结果将是:

id,project-id,subject,description,Delay,Means of Delivery,Shipping Date
100,10,first helpdesk issue,a small problem,15,,2016-08-01
101,10,second helpdesk issue,a medium problem,10,FTP,
102,10,third helpdesk issue,a huge security problem,,SSH,
103,20,first "development" issue,just some "strange" software,,,

关于xml - 在 xslt 模板中创建 key ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38779288/

有关xml - 在 xslt 模板中创建 key的更多相关文章

  1. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  2. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  3. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

  4. ruby - 如何在 Ruby 中创建无类 DSL? - 2

    我正在尝试找出如何为我的Ruby项目创建一种“无类DSL”,类似于在Cucumber步骤定义文件中定义步骤定义或在Sinatra应用程序中定义路由。例如,我想要一个文件,其中调用了我的所有DSL函数:#sample.rbwhen_string_matches/hello(.+)/do|name|call_another_method(name)end我认为用我的项目特有的一堆方法污染全局(内核)命名空间是一种不好的做法。因此方法when_string_matches和call_another_method将在我的库中定义,并且sample.rb文件将以某种方式在我的DSL方法的上下文中

  5. ruby-on-rails - 如何在 Rails 3 中创建自定义脚手架生成器? - 2

    有这些railscast。http://railscasts.com/episodes/218-making-generators-in-rails-3有了这个,你就会知道如何创建样式表和脚手架生成器。http://railscasts.com/episodes/216-generators-in-rails-3通过这个,您可以了解如何添加一些文件来修改脚手架View。我想把两者结合起来。我想创建一个生成器,它也可以创建脚手架View。有点像RyanBates漂亮的生成器或web_app_themegem(https://github.com/pilu/web-app-theme)。我

  6. ruby - 为什么在 ruby​​ 中创建 Rational 不需要新方法 - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Rubysyntaxquestion:Rational(a,b)andRational.new!(a,b)我正在阅读ruby镐书,我对创建有理数的语法感到困惑。Rational(3,4)*Rational(1,2)产生=>3/8为什么Rational不需要new方法(我还注意到例如我可以在没有new方法的情况下创建字符串)?

  7. ruby-on-rails - Mandrill API 模板 - 2

    我正在使用Mandrill的RubyAPIGem并使用以下简单的测试模板:testastic按照Heroku指南中的示例,我有以下Ruby代码:require'mandrill'm=Mandrill::API.newrendered=m.templates.render'test-template',[{:header=>'someheadertext',:main_section=>'Themaincontentblock',:footer=>'asdf'}]mail(:to=>"JaysonLane",:subject=>"TestEmail")do|format|format.h

  8. ruby - 在 Ruby 中创建按公共(public)键值分组的新哈希 - 2

    假设我有一个在Ruby中看起来像这样的哈希:{:ie0=>"Hi",:ex0=>"Hey",:eg0=>"Howdy",:ie1=>"Hello",:ex1=>"Greetings",:eg1=>"Goodday"}有什么好的方法可以将它变成如下内容:{"0"=>{"ie"=>"Hi","ex"=>"Hey","eg"=>"Howdy"},"1"=>{"ie"=>"Hello","ex"=>"Greetings","eg"=>"Goodday"}} 最佳答案 您要求一个好的方法来做到这一点,所以答案是:一种您或同事可以在六个月后理解

  9. ruby - Chef Ruby 遍历 .erb 模板文件中的属性 - 2

    所以这可能有点令人困惑,但请耐心等待。简而言之,我想遍历具有特定键值的所有属性,然后如果值不为空,则将它们插入到模板中。这是我的代码:属性:#===DefaultfileConfigurations#default['elasticsearch']['default']['ES_USER']=''default['elasticsearch']['default']['ES_GROUP']=''default['elasticsearch']['default']['ES_HEAP_SIZE']=''default['elasticsearch']['default']['MAX_OP

  10. ruby-on-rails - Ruby - 如何从 ruby​​ 上的 .pfx 文件中提取公钥、rsa 私钥和 CA key - 2

    我有一个.pfx格式的证书,我需要使用ruby​​提取公共(public)、私有(private)和CA证书。使用shell我可以这样做:#ExtractPublicKey(askforpassword)opensslpkcs12-infile.pfx-outfile_public.pem-clcerts-nokeys#ExtractCertificateAuthorityKey(askforpassword)opensslpkcs12-infile.pfx-outfile_ca.pem-cacerts-nokeys#ExtractPrivateKey(askforpassword)o

随机推荐