nick78
nick78

Reputation: 261

apache camel split() vs. split(body())

I have a problem using the split component. I want to split a large xml file to multiple small files. In the small files I want to group 25 elements together. My first Intention was using the following:

from(direct:start)
.split().tokenizeXML("SomeElement", 25)
... 

But then I get this error:

SaxParseException: Cannot find the declaration of element 'SomeElement'

Then I tried

.split(body().tokenizeXML("SomeElement", "*"))

And yeah this worked BUT, split takes an Expression as parameter, and with the Expression body().tokenizeXML("SomeElement", "*") there is no chance to use the grouping feature. So my question is, 1. Why does split() not find the element? 2. Is there a chance to use the group feature in split(Expression)?

Since we are bound to Java 6 we use camel version 2.13.4.

The XML File looks like this (simplified, imagine there are hundreds of SomeElement elements inside MyRootElement)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MyRootElement xmlns="urn:THIS:IS:A-NAMESPACE">
    <SomeElement id="12345">
        <address addressType="mainAddress" street="Test street" zipCode="12345" city="Testcity"/>
    </SomeElement>
    <SomeElement id="23456">
        <address addressType="mainAddress" street="Test street" zipCode="12345" city="Testcity"/>
    </SomeElement>
</MyRootElement>

EDIT:

OK, after doing the changes suggested by fiw, it works now.

But now my validation fails. While .split(body().tokenizeXML("SomeElement", "*")) embeds SomeElement within MyRootElement, so that I get splitted messages like this:

<MyRootElement xmlns="urn:THIS:IS:A-NAMESPACE" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="urn:THIS:IS:A-NAMESPACE">
        <SomeElement id="12345">
            <address addressType="mainAddress" street="Test street" zipCode="12345" city="Testcity"/>
        </SomeElement>
</MyRootElement>

split().tokenizeXML("SomeElement", 2) does not consider the root element and the namespace, so I get something like this:

    <SomeElement id="12345">
                <address addressType="mainAddress" street="Test street" zipCode="12345" city="Testcity"/>
    </SomeElement>
    <SomeElement id="23456">
                <address addressType="mainAddress" street="Test street" zipCode="12345" city="Testcity"/>
    </SomeElement>

Naturally if I validate the splitted message against the schema It fails. Because I need the SomeElements embedded within the root element MyRootElement like this:

<MyRootElement xmlns="urn:THIS:IS:A-NAMESPACE" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="urn:THIS:IS:A-NAMESPACE">
  <SomeElement id="12345">
            <address addressType="mainAddress" street="Test street" zipCode="12345" city="Testcity"/>
  </SomeElement>
  <SomeElement id="23456">
            <address addressType="mainAddress" street="Test street" zipCode="12345" city="Testcity"/>
  </SomeElement>
</MyRootElement>

Upvotes: 3

Views: 6413

Answers (1)

fiw
fiw

Reputation: 756

This test of grouping and xml splitting passed for me:

public class TestSplitOnXml extends CamelTestSupport {

    @Override
    protected RouteBuilder createRouteBuilder() throws Exception {
        return new RouteBuilder() {
            @Override
            public void configure() throws Exception {
                from("direct:in")
                    .split().tokenizeXML("SomeElement", 2)
                        .to("mock:out")
                        .end();
            }
        };
    }

    @Test
    public void testSplitting() throws InterruptedException {
        MockEndpoint mockEndpoint = getMockEndpoint("mock:out");
        mockEndpoint.setExpectedMessageCount(2);

        Exchange exchange = createExchangeWithBody(this.getClass().getClassLoader().getResourceAsStream("text.xml"));
        template.send("direct:in", exchange);

        assertMockEndpointsSatisfied();
    }
}

with this as test.xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MyRootElement xmlns="urn:THIS:IS:A-NAMESPACE" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="urn:THIS:IS:A-NAMESPACE">
    <SomeElement id="12345">
        <address addressType="mainAddress" street="Test street" zipCode="12345" city="Testcity"/>
    </SomeElement>
    <SomeElement id="23456">
        <address addressType="mainAddress" street="Test street" zipCode="12345" city="Testcity"/>
    </SomeElement>
    <SomeElement id="23456">
        <address addressType="mainAddress" street="Test street" zipCode="12345" city="Testcity"/>
    </SomeElement>
    <SomeElement id="23456">
        <address addressType="mainAddress" street="Test street" zipCode="12345" city="Testcity"/>
    </SomeElement>
</MyRootElement>

From this you can see that the split, tokeniseXML and grouping does work. It may be that your xml is just missing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:THIS:IS:A-NAMESPACE"

Upvotes: 1

Related Questions