Kettle - 生成xml文件

本文详细介绍了如何使用开源工具Kettle生成复杂XML文件,包括利用Excel数据、组件组合和XSLT转换等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Kettle 使用备忘录 1- 生成xml文件

  (2012-06-12 10:36:36)
标签: 

it

分类: ETL
最近被抓壮丁去弄一个ETL的项目,要求用开源的kettle去替代原来平台上的datastage。
本文主要是记录下在使用kettle过程中碰到的头疼的问题和解决方案。。。

1. 利用 excel中的数据生成xml文件

kettle中的xml文件输出组件的功能其实是很弱的,所以要生成较为复杂的xml文件时需要使用组件:
add xml ,   xml join,   placeholder, js script 等等
如下是一个例子:
Kettle <wbr>使用备忘录 <wbr>1- <wbr>生成xml文件
使用merge join主要是为了减少在xml join中需要匹配的结果集合(因为xml join中的匹配功能其实是很弱的)。
在merge join之前记录必须先排序。
placeholder 组件是往记录流中添加一个常量,这个常量在 add xml中通常不被设为属性,而是在xml join中用于放置需要被组装进去的xml元素。
以生成如下简单的xml文件为例:
<?xml version="1.0" encoding="UTF-8"?>
<document>
       <section name="foo">
       <p>
              Hello from section foo
       </p>
       </section>
       <section name="bar">
       <p>
               Hello from section bar
       </p>
       </section>
</document>
对应的kettle 转换为:
Kettle <wbr>使用备忘录 <wbr>1- <wbr>生成xml文件

首先需要从excel文件中读取数据,excel文件中的内容为
Kettle <wbr>使用备忘录 <wbr>1- <wbr>生成xml文件
利用读取到的内容生成xml元素,如下是add xml中的设置:
Kettle <wbr>使用备忘录 <wbr>1- <wbr>生成xml文件

Kettle <wbr>使用备忘录 <wbr>1- <wbr>生成xml文件
这一步主要生成了如下的xml元素:
<section name="foo">
       <p>
              Hello from section foo
       </p>
</section>
<section name="bar">
       <p>
               Hello from section bar
       </p>
   </section>
接下来要生成 <document>元素,因为该元素没有对应的数据,所以使用“生成记录”组件生成一条空记录用于与之前的xml元素进行xml join。它的功能有点类似与之前提到的placeholder,不同的是这个可以作为起始输入,而placeholder是一个转换步骤。
Kettle <wbr>使用备忘录 <wbr>1- <wbr>生成xml文件
然后是利用这条生成的记录生成xml元素document,注意属性选否:
Kettle <wbr>使用备忘录 <wbr>1- <wbr>生成xml文件

Kettle <wbr>使用备忘录 <wbr>1- <wbr>生成xml文件

接着就是进行xml join了,source stream中的xml元素会被拼接到target stream的xml元素中。怎么拼接有join condition properties决定,它是使用xpath来定位要拼接的位置,例如//doc 就是把source stream的元素拼接到每个doc元素中。需要注意的是,由于这次xml join之后xml文件就生成好了,所以不能把omit xml header选上。
Kettle <wbr>使用备忘录 <wbr>1- <wbr>生成xml文件
当然通过xpath也可以做复杂的条件join,如下是个例子:
Kettle <wbr>使用备忘录 <wbr>1- <wbr>生成xml文件

可以通过xpath指定在所有target stream的area元素中如果area的属性STATIONID的值与source stream中STATIONID的值(这个值不一定要在source的xml元素中,但必须在source stream中,例如可以是一开始从excel读入的流中)相同,那么把source stream中的xml元素放到 orderlinecomments元素中。

这步之后生成的xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<document>
  <doc>
       <section name="foo">
       <p>
              Hello from section foo
       </p>
       </section>
       <section name="bar">
       <p>
               Hello from section bar
       </p>
       </section>
  </doc>
</document>
和我们预期的多了<doc>和</doc>,这是我们使用js脚本进行替换:
Kettle <wbr>使用备忘录 <wbr>1- <wbr>生成xml文件

js脚本处理好之后,输出流的名字就换成 xmlOderLinesNew了。
最后把这个流输出到文件中,需要注意的是在内容中不要使用“分割符”,“封闭符”,和“头部”:
Kettle <wbr>使用备忘录 <wbr>1- <wbr>生成xml文件

Kettle <wbr>使用备忘录 <wbr>1- <wbr>生成xml文件

Kettle <wbr>使用备忘录 <wbr>1- <wbr>生成xml文件


--关于kettle生成xml文件的性能问题
各个步骤中addxml的效率不错,但是xmljoin在大数据量的情况下效率实在太低。。。,按照我的理解,kettle通过addxml生成一个xml内容的字符串,然后xmljoin其实是对两个大字符串进行重构,这个重构过程还涉及到字符子串的定位,拷贝,比较,甚至是字符串子串级别的join。。。效率很难能高,所以在数据量比较大的时候应该避免使用xmljoin。
其实我们使用xmljoin主要是为了生成层次化的xml文件。作为替代方案,首先在使用addxml生成xml字符串之前,先使用merge join把目标xml文件中所需的数据先生成出来,这个时候生成的xml字符串中的xml是几乎没有层次的:
例如
<?xml version="1.0" encoding="ISO-8859-1"?>
<Users>
<User id="2" name="ABC" Division="HR" country="C"/>
<User id="3" name="xyz" Division="Admin" country="D"/>
<User id="4" name="LMN" Division="Admin" country="D"/>
<User id="5" name="PQR" Division="HR" country="C"/>
</Users>
然后我们可以通过xslt进行xml文件结构的重构,xsl文件的示例如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

       <xsl:output method="xml" indent="yes" />

       <xsl:key name="division" match="User" use="concat(@Division, ',', @country)" />

       <xsl:template match="Users">
               <AllUsers>
                       <xsl:apply-templates select="User[generate-id()=generate-id(key('division',concat(@Division, ',', @country))[1])]"/>
               </AllUsers>
       </xsl:template>

       <xsl:template match="User">
               <Division value="{@Division}" country="{@country}">
                       <xsl:for-each select="key('division', concat(@Division, ',', @country))">
                               <User id="{@id}" name="{@name}"/>
                       </xsl:for-each>
               </Division>
       </xsl:template>

</xsl:stylesheet>
生成的目标xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<AllUsers>
<Division country="C" value="HR">
<User name="ABC" id="2"/>
<User name="PQR" id="5"/>
</Division>
<Division country="D" value="Admin">
<User name="xyz" id="3"/>
</Division>
<Division country="D" value="Payroll">
<User name="LMN" id="4"/>
</Division>
</AllUsers>

具体到kettle中我们可以使用xsl transformation组件来进行转换:
Kettle <wbr>使用备忘录 <wbr>1- <wbr>生成xml文件
其中的xsl 转换:
Kettle <wbr>使用备忘录 <wbr>1- <wbr>生成xml文件

理想的状态是我们直接使用转换中的XSL Transformation组件,在转换级别就解决问题,但事与愿违,这个步骤老是报错。。。 Kettle <wbr>使用备忘录 <wbr>1- <wbr>生成xml文件
只好使用job级别的XSL Transformation组件,这样会比较麻烦,要先通过一个转换生成中间xml文件保存到磁盘,然后在调用XSL Transformation组件读取这个中间xml文件以及定义好的xsl文件生成目标xml文件。。
Kettle <wbr>使用备忘录 <wbr>1- <wbr>生成xml文件

还有一种思路是不使用kettle的xsl transformation组件,而是直接在kettle的User Define Java Class组件中通过java代码调用xsl文件进行转换,java代码调用xsl文件和xml文件进行转换的代码可以参考:
http://www.blogjava.net/yangxiang/archive/2009/08/11/290688.html

关于xsl文件的编写可以参考
http://stackoverflow.com/questions/2146648/how-to-apply-group-by-on-xslt-elements
<think>好的,我现在需要解决用户遇到的Pentaho Kettle插件找不到的问题。用户提到了两个错误信息,一个是无法找到ID为'Kettle'的插件,另一个是SWT库加载失败。我需要先理清这些错误的原因,然后给出解决方案。 首先,根据引用[1]中的信息,错误提示明确指出如果这是一个测试环境,需要确保kettle-core的测试jar包被正确依赖;如果是生产环境,需要检查类路径下是否存在kettle-password-encoder-plugins.xml文件。这说明用户可能在构建项目时缺少了必要的依赖或配置文件。 接下来,引用[2]中的错误提到了SWT库的问题,但同时也重复了关于Kettle插件找不到的信息。SWT库的问题可能与运行环境有关,比如缺少GTK库或者SWT的本地库文件没找到。不过用户主要关注的是Kettle插件的问题,所以可能需要优先解决依赖问题,再看是否SWT错误是连带出现的。 我应该分步骤来解决。首先检查项目的依赖配置,确保kettle-core及其测试jar包被正确引入。例如,在Maven项目中,需要确认pom.xml文件中是否包含kettle-core的依赖,尤其是测试用的jar包是否在test范围内。如果用户使用的是其他构建工具,如Gradle,也需要检查相应的配置。 然后,关于kettle-password-encoder-plugins.xml文件,这个文件需要存在于类路径中。用户可能需要手动创建这个文件,或者从Kettle的安装目录中复制过来。需要确认文件的位置是否正确,比如在Maven项目中,通常放在src/main/resources目录下,这样构建时会自动包含到类路径中。 此外,用户提到的SWT库加载失败,可能需要检查运行环境是否安装了GTK相关的库,或者SWT的jar包是否正确引入。不过这可能属于另一个问题,如果解决了Kettle插件的问题后仍然存在,可能需要单独处理。 在解决问题时,可能还需要清理和重新构建项目,确保所有依赖都被正确下载和包含。例如,在Maven中使用mvn clean install命令,或者刷新项目依赖。 最后,用户可能需要验证解决方案是否有效,例如运行测试用例或启动应用程序,确认错误是否消失。如果仍然存在问题,可能需要进一步检查依赖版本是否兼容,或者配置文件是否有语法错误。 总结来说,解决方案应包括检查依赖配置、添加必要的配置文件、处理可能的运行环境问题,并验证结果。需要分步骤指导用户操作,确保每个环节都正确执行。</think>### Pentaho Kettle插件未找到问题的解决方案 #### 问题分析 该错误通常由以下原因导致: 1. **缺少依赖项**:未正确引入`kettle-core`的测试JAR包(测试环境)[^1] 2. **配置文件缺失**:生产环境中缺少`kettle-password-encoder-plugins.xml`文件[^1] 3. **类路径配置错误**:文件未放置在可识别的资源目录中 --- #### 分步解决方案 **1. 添加测试依赖(针对测试环境)** 在Maven项目的`pom.xml`中添加: ```xml <dependency> <groupId>org.pentaho</groupId> <artifactId>kettle-core</artifactId> <version>YOUR_KETTLE_VERSION</version> <scope>test</scope> </dependency> ``` *注意:需替换`YOUR_KETTLE_VERSION`为实际版本号,例如`8.3.0.7-719`* **2. 创建配置文件(生产环境)** 新建`kettle-password-encoder-plugins.xml`文件,内容示例: ```xml <password-encoder-plugins> <password-encoder-plugin class="org.pentaho.di.core.encryption.EncodePasswordEncoderPlugin"/> </password-encoder-plugins> ``` 放置位置: - Maven项目:`src/main/resources` - Gradle项目:`src/main/resources` - 独立应用:类路径根目录 **3. 验证类路径配置** 使用以下代码检查文件是否加载: ```java InputStream is = getClass().getResourceAsStream("/kettle-password-encoder-plugins.xml"); System.out.println("File exists: " + (is != null)); ``` **4. 清理并重建项目** 执行Maven命令: ```bash mvn clean install -U ``` --- #### 附加建议 1. 若同时出现`SWT library`错误,需确保: - 安装GTK 2.0运行时库 - 添加SWT依赖: ```xml <dependency> <groupId>org.eclipse.platform</groupId> <artifactId>org.eclipse.swt.gtk.linux.x86_64</artifactId> <!-- 根据系统调整 --> <version>3.115.100</version> </dependency> ``` 2. 检查Pentaho Kettle版本与其他依赖的兼容性 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值