转换xml标记

时间:2013-04-29 13:43:29

标签: java xml dom

我需要像这样进行转换:

给出(许多中的一个):

    <Field name="topmostSubform[0].Page1[0].MemberID[0]" value="025620451" />

我需要将它转换为像这样的xml:

<?xml version="1.0" encoding="UTF-8"?>
<topmostSubform ind="0">
     <page ind ="0">
         <MemeberID ind="0">025620451</MemeberID>
     </page>
</topmostSubform>

我得到了一大堆字段,例如我需要转换为一个xml的示例。

字段标记可以包含更多标记,然后是示例。

您建议采用什么方法?

难点在于使用什么数据结构?我怎么能填充这个数据库,所以最终我可以创建一个xml?

我尝试在迭代输入时使用DOM构建xml,但在这种情况下我创建了大量重复的标记。

感谢。

1 个答案:

答案 0 :(得分:1)

xpath的组合,用于检查元素是否已存在和递归将执行您想要的操作。

这就是我提出的:

import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class Transformation 
{
  private static final XPath XPATH = XPathFactory.newInstance().newXPath();

  public static void main(String[] args) 
  {
    try 
    {
      DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();

      Document xml1 = documentBuilder.parse(new ByteArrayInputStream("<Field name=\"topmostSubform[0].Page[0].MemberID[0]\" value=\"1\"/>".getBytes()));
      Document xml2 = documentBuilder.parse(new ByteArrayInputStream("<Field name=\"topmostSubform[0].Page[0].MemberID[1]\" value=\"2\"/>".getBytes()));
      Document xml3 = documentBuilder.parse(new ByteArrayInputStream("<Field name=\"topmostSubform[0].Page[1].MemberID[0]\" value=\"3\"/>".getBytes()));
      Document xml4 = documentBuilder.parse(new ByteArrayInputStream("<Field name=\"topmostSubform[1].Page[0].MemberID[0]\" value=\"4\"/>".getBytes()));

      Document document = documentBuilder.newDocument();
      document.appendChild(document.createElement("root"));

      //Loop through each piece of XML creating elements in the single document as necessary.
      for (Document xml : new Document[]{xml1, xml2, xml3, xml4}) 
      {
        Element fieldElement = (Element)XPATH.evaluate("/Field", xml, XPathConstants.NODE);

        String name = fieldElement.getAttribute("name");
        String value = fieldElement.getAttribute("value");

        createElements(
          document, 
          document.getDocumentElement(), 
          new ArrayList<String>(Arrays.asList(name.split("\\."))), 
          value
        );
      }

      //Print the result at the command line.
      Transformer transformer = TransformerFactory.newInstance().newTransformer();
      transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");

      StringWriter writer = new StringWriter();
      transformer.transform(new DOMSource(document), new StreamResult(writer));

      System.out.println(writer.getBuffer().toString());
    }
    catch (Exception e) 
    {
      e.printStackTrace();
    }
  }

  /**
   * Creates child elements under the <code>parent</code> based on the <code>nameTokens</code>.
   */
  private static void createElements(Document document, Element parent, List<String> nameTokens, String value) throws XPathExpressionException 
  {
    String nameToken = nameTokens.remove(0);

    String name = nameToken.substring(0, nameToken.indexOf("["));
    String index = nameToken.substring(nameToken.indexOf("[") + 1, nameToken.indexOf("]"));

    Element element = (Element)XPATH.evaluate(name + "[@ind=" + index + "]", parent, XPathConstants.NODE);
    if (element == null) 
    {
      element = document.createElement(name);
      element.setAttribute("ind", index);
      parent.appendChild(element);
    }

    if (nameTokens.isEmpty()) 
    {
      element.appendChild(document.createTextNode(value));
    }
    else 
    {
      createElements(document, element, nameTokens, value);
    }
  }
}

其中(格式化后)打印出来:

<root>
  <topmostSubform ind="0">
    <Page ind="0">
      <MemberID ind="0">1</MemberID>
      <MemberID ind="1">2</MemberID>
    </Page>
    <Page ind="1">
      <MemberID ind="0">3</MemberID>
    </Page>
  </topmostSubform>
    <topmostSubform ind="1">
      <Page ind="0">
        <MemberID ind="0">4</MemberID>
      </Page>
    </topmostSubform>
 </root>