Christopher Klewes
Christopher Klewes

Reputation: 11435

Transform XML based on a template with custom logic. Which framework? How to achieve streaming?

I want to modify a XML template with a custom logic, it's similiar to XSLT but has some very own features. The XML template file is clean and ready to expand.

  <user-list>
    <user id="">
      <forename></forename>
      <lastname></lastname>
      <static-information>static</static-information>

      <address-list>
         <address>
           ...
         </address>
      </adress-list>
    </user>
  </user-list> 

Now I receive a JDBC result set for this template and a mapping for the datastructure with informations about repeating nodes (like "user"-node here) and mapping hints (e.g. "user/forename" to FORENAME {a SQL column}).

  <user-list>
    <user id="1">
      <forename>stack</forename>
      <lastname>overflow</lastname>
      <static-information>static</static-information>
      <address-list>...</adress-list>
    </user>
    <user id="2">
      <forename>questions</forename>
      <lastname>answers</lastname>
      <static-information>static</static-information>
      <address-list>...</adress-list>
    </user>
  </user-list> 

The mapping has relative informations about inner nodes which shall expand (the address should be repeated if the current user has more than one address.

  <query>SELECT * FROM USER</query>
  <element>user/address-list/address</element>
  <mapping element="street" source="STREET"></mapping>

This could be a very complex model that can contain up to 10000 entries. How can I achieve the transformation from a easy template without knowing it's structure (beside the small informations given by the mapping). What framework should I choose? How can I achieve streaming? I don't want to transform and do the mapping in memory. After each complete e.g. user block the streaming can go on.

Thank you

Upvotes: 0

Views: 647

Answers (2)

Peter Knego
Peter Knego

Reputation: 80330

You can use a STaX parser like Woodstox. Then create a reading loop and embed inside it write commands that write out XML elements based on input element.

An example that reads simple elements and writes them to output, except for <address-list> element where it creates a series of <address></address> subelements inside it:

FileInputStream fis = new FileInputStream(file);

XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader staxXmlReader = factory.createXMLStreamReader(fis);

XMLOutputFactory outFactory = XMLOutputFactory.newInstance();
XMLStreamWriter staxWriter = outFactory.createXMLStreamWriter(out);

for (int event = staxXmlReader.next(); event != XMLStreamConstants.END_DOCUMENT; 
     event = staxXmlReader.next()) {

    switch (event) {
    case XMLStreamConstants.START_DOCUMENT:
        break;
    case XMLStreamConstants.START_ELEMENT:
        String elementName = staxXmlReader.getLocalName();
        if(elementName.equals("address-list")){
            staxWriter.writeStartElement(elementName);
            String addressText = staxXmlReader.getElementText();
            // parse element text
            // and loop creating <address> elements
            for (..) {
                staxWriter.writeStartElement("address");  // write <address>
                staxWriter.writeCharacters("address data");
                staxWriter.writeEndElement();  // write </address>
            }
        } else {
            // just copy the element
            staxWriter.writeStartElement(elementName);
            staxWriter.writeCharacters(staxXmlReader.getElementText());
        }
        break;
    case XMLStreamConstants.END_ELEMENT:
        staxWriter.writeEndElement();
        break;
    case XMLStreamConstants.END_DOCUMENT:
        staxWriter.writeEndDocument();
        break;
    default:
         break;
    }
}

Upvotes: 3

lexicore
lexicore

Reputation: 43651

Another options would be using extension functions and elements in XSLT. Saxon is for instance very good in supporting such things.

Upvotes: 0

Related Questions