Как расширить несколько дочерних элементов XML Camel? - PullRequest
0 голосов
/ 14 ноября 2018

У меня есть сценарий использования, когда мне нужно взять существующий документ XML и дополнить его из базы данных для процесса интеграции.

Я начинаю с чего-то вроде:

<parent>
  <child>
    <data>A</data>
  </child>
  <child>
    <data>B</data>
  </child>
  <parentData>
    <data/>
  </parentData>
</parent>

То, что я пытаюсь сделать, это добавить дерево <moreData .../> к каждому из child элементов.

Я мог бы просто написать собственный bean-компонент, который делает все, но в нем нет правильного подхода,Я подумал об использовании разделителя на основе xpath для child, за которым следует content-enricher, который позволит мне получить дополнительные данные, но я не вижу, как потом собрать все заново.

Atв данный момент я думаю, что мне нужно использовать цикл, но это тоже кажется неуклюжим и потребует настраиваемой стратегии агрегирования для обогащения контента.

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() )

Это должно происходить каждый день вМир верблюда, но я не могу найти примеров того, как это сделать.

Если бы я делал это в пользовательском бине, я бы получил xpath для элемента child, а затем прошел бы черезнода, выполняющая запрос и присоединяющая результат как новый дочерний элемент к узлу.Я просто не могу понять, как сделать это "красиво" в Camel.

Любые идеи или подсказки были бы великолепны!Спасибо!

1 Ответ

0 голосов
/ 14 ноября 2018

Вы можете попробовать подготовить карту новых узлов, а затем преобразовать родительский xml с помощью xslt и получить подготовленные новые узлы, используя java внутри xsl. Вот несколько примеров. Маршрут:

 @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 - боб класса:

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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...