apache-camel - 如何增加多个 XML 子元素 Camel?
问题描述
我有一个用例,我需要从数据库中获取现有的 XML 文档并对其进行扩充,以进行集成过程。
我从以下内容开始:
<parent>
<child>
<data>A</data>
</child>
<child>
<data>B</data>
</child>
<parentData>
<data/>
</parentData>
</parent>
我想要做的是为每个元素添加一<moreData .../>
棵树。child
我可以编写一个可以做所有事情的自定义 bean,但这感觉不是正确的方法。我考虑过使用基于 xpath for child 的拆分器,然后是内容丰富器,这将允许我获取额外的数据,但我看不到如何在之后重新组装所有内容。
目前,我在想我需要使用循环,但这也感觉很笨拙,并且需要为内容丰富的自定义聚合策略。
from("direct:a")
.loop().xpath("count( parent/child )", Integer.class )
.setHeader("Key")
.xpath( "parent/child[function:properties('CamelLoopIndex')]/data", String.class )
.enrich("sql:SELECT xmldata FROM dataTable WHERE key = :#Key?dataSource=myDS",
new MyCustomAggregationStrategy() )
这一定是骆驼世界中每天都会发生的事情,但我找不到任何如何做到这一点的例子。
如果我在自定义 bean 中执行此操作,我将获得child
元素的 xpath,然后遍历执行查询的节点集并将结果作为新子节点附加到节点。我只是看不到如何在骆驼中“很好地”做到这一点。
任何想法或提示都会很棒!谢谢!
解决方案
您可以尝试准备新节点的映射,然后使用 xslt 转换父 xml,并使用 xsl 中的 java 获取准备好的新节点。这里有一些例子。路线:
@Override
public void configure() throws Exception {
from("timer://foo?period=30s")
.setBody(constant("<parent>\n" +
" <child>\n" +
" <data>A</data>\n" +
" </child>\n" +
" <child>\n" +
" <data>B</data>\n" +
" </child>\n" +
" <parentData>\n" +
" <data/>\n" +
" </parentData>\n" +
"</parent>"))
.convertBodyTo(org.w3c.dom.Document.class)
.setProperty("oldBody", simple("body"))
.split(xpath("//child"), (oldExchange, newExchange) -> {
Map<String, String> map = oldExchange != null ? oldExchange.getProperty("map", Map.class) : new HashMap<>();
map.put(newExchange.getIn().getHeader("Key", String.class), newExchange.getIn().getBody(String.class));
newExchange.setProperty("map", map);
return newExchange;
})
.setHeader("Key", xpath("//data/text()"))
// .to("sql:SELECT xmldata FROM dataTable WHERE key = :#Key?dataSource=#myDS")
//emulate result of your sql
.process(exchange -> {
exchange.getIn().setBody("<someNewData>".concat(exchange.getIn().getHeader("Key", String.class).concat("Result")).concat("</someNewData>"));
})
.end()
.setBody(exchangeProperty("oldBody"))
.to("xslt:xslt/result.xsl?transformerFactory=#nsTF")
.log(LoggingLevel.INFO, "Body:${body}");}
public static String getElement(Object map, String key) {
return (String) ((Map) map).get(key);
}
nsTF 是 bean 类:
public class NonSecureTransfomerFactory extends TransformerFactoryImpl {
@Override
//for using java inside xsl
public boolean isSecureProcessing()
{
return false;
}
}
xslt 样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:getter="my.package.RouteHelper">
<xsl:output method="xml" version="1.0" encoding="UTF-8"/>
<xsl:strip-space elements='*'/>
<xsl:param name="map"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="child">
<xsl:copy>
<xsl:variable name="key" select="data/text()"/>
<xsl:value-of disable-output-escaping="yes" select="getter:getElement($map,$key)"/>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
输出xml:
<parent>
<child>
<someNewData>AResult</someNewData>
<data>A</data>
</child>
<child>
<someNewData>BResult</someNewData>
<data>B</data>
</child>
<parentData>
<data/>
</parentData>
</parent>
推荐阅读
- javascript - 从过滤器内部的过滤器获取结果的问题
- html - 关键帧动画适用于 Chrome 和 Edge,但不适用于 Firefox
- javascript - 如何在 HTML 页面上选择图像的子区域并将坐标发送到服务器
- azure-web-app-service - 范围参数中的 Azure Easy Auth 和基于资源的权限
- python - 通过 python 脚本将 JSON 文件添加到 .xcodeproj?
- rust - 为迭代器创建 peek_while
- java - java - 如何使用VTA算法为java创建带有soot和spark的调用图?
- google-apps-script - 使用 Apps 脚本将字体系列从 Google 表单更改为 Google Doc
- scala - 如何定义一个空查询
- google-sheets - Google 表格 - 打开特定选项卡时自动运行脚本