代码之家  ›  专栏  ›  技术社区  ›  Christopher Klewes

基于具有自定义逻辑的模板转换XML。哪个框架?如何实现流媒体?

  •  0
  • Christopher Klewes  · 技术社区  · 14 年前

    我想用自定义逻辑修改一个XML模板,它类似于XSLT,但有一些非常独特的特性。XML模板文件是干净的,可以扩展。

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

    现在,我收到了这个模板的JDBC结果集和数据结构的映射,其中包含有关重复节点(如“user”-这里的节点)和映射提示(如“user/forename”到forename SQL列)的信息。

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

    映射具有有关内部节点的相关信息,这些信息应展开(如果当前用户有多个地址,则应重复该地址)。

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

    这可能是一个非常复杂的模型,最多可以包含10000个条目。如何在不知道简单模板结构的情况下实现转换(除了映射给出的小信息)。我应该选择什么框架?如何实现流媒体?我不想在内存中转换和映射。每次完成后,例如用户阻止后,可以继续进行流式处理。

    谢谢你

    2 回复  |  直到 11 年前
        1
  •  3
  •   ziesemer    11 年前

    你可以使用 STaX 类解析器 Woodstox . 然后创建一个读取循环,并在其中嵌入写基于输入元素写出XML元素的命令。

    一个读取简单元素并将其写入输出的示例,除了 <address-list> 元素,在其中创建一系列 <address></address> 其中的子元素:

    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;
        }
    }
    
        2
  •  0
  •   lexicore    14 年前

    另一个选项是在XSLT中使用扩展函数和元素。例如,撒克逊非常擅长支持这类事情。