如何使用VTD-XML以编程方式创建xml?

时间:2017-08-02 11:24:25

标签: java xml vtd-xml

我想创建一个具有此形状的xml,我将内部元素/a/b插入循环中,并在元素b上设置属性。

<ROOT>
  <a>
    <b attr1="1" attr2="a"/>
  </a>
  <a>
    <b attr1="1" attr2="b"/>
  </a>
  <a>
    <b attr1="2" attr2="a"/>
  </a>
  <a>
    <b attr1="2" attr2="b"/>
  </a>
</ROOT>

这是我到目前为止的代码:

  public static String createXML(Collection<Integer> numbers, Collection<String> words) {
    String charsetName = "UTF-16";
    byte[] root = "<ROOT></ROOT>".getBytes(charsetName);
    VTDGen vg = new VTDGen();
    AutoPilot ap = new AutoPilot();
    ap.selectXPath("/ROOT");
    XMLModifier xm = new XMLModifier();
    vg.setDoc(root);
    vg.parse(false);
    VTDNav vn = vg.getNav();
    ap.bind(vn);
    xm.bind(vn);

    byte[] aTag = "<a></a>".getBytes(charsetName);
    byte[] bTag = "<b />".getBytes(charsetName);

    int i;

    String collect = numbers.stream().flatMap(number -> words.stream().map(word -> {
      try {
        xm.insertAfterHead(aTag);
        ap.selectXPath("a");
        xm.insertAfterHead(bTag);
        ap.selectXPath("b");
        xm.insertAttribute(String
          .format(" attr1=\"%d\" attr2=\"%s\"",
            number,
            word));
        return xm.outputAndReparse().toNormalizedString(0);
      } catch (ModifyException | NavException | ParseException | IOException | TranscodeException | XPathParseException e) {
        throw new RuntimeException(e);
      }
    }))
      .collect(Collectors.joining(""));

    return collect;
  }

我得到一个ModifyExcpetion因为我两次调用insertAfterHead。 如何生成所需的xml形状?我还不完全了解如何将偏移量放到正确的位置。

1 个答案:

答案 0 :(得分:1)

我想我可能知道你想要完成什么。有一些建议

  • selectXPath(a)仅将xpath编译为内部格式...它不会为您评估节点集。要评估它,您需要调用evalXPath()。

  • 您希望将尽可能多的插入根节点下作为单个字符串连接。实际的字符串连接操作应作为应用程序逻辑的独立部分发生。在VTD-XML中,您可以考虑位字节,字节数组和整数/长数组。

以下是我的代码模型。

public static void main(String[] args) throws VTDException,IOException,
    UnsupportedEncodingException{
        String charsetName = "UTF-16";
        byte[] root = "<ROOT><a><b/></a><a><b/></a><a><b/></a><a><b/></a></ROOT>"
    .getBytes(charsetName); // that is template you want to start with
        VTDGen vg = new VTDGen();
        AutoPilot ap = new AutoPilot();
        ap.selectXPath("/ROOT/a/b");
        XMLModifier xm = new XMLModifier();
        vg.setDoc(root);
        vg.parse(false);
        VTDNav vn = vg.getNav();
        ap.bind(vn);
        xm.bind(vn);
        int i=0;
        int[] ia = new int[4];
        ia[0]=1;ia[1]=1;ia[2]=2;ia[3]=2;
        String[] sa = new String[4];
        sa[0]="a";sa[1]="b";sa[2]="a";sa[3]="b";
        int k=0;
        while((i=ap.evalXPath())!=-1){
            xm.insertAttribute( String.format(" attr1=\"%d\" attr2=\"%s\"",
                    ia[k],
                    sa[k]));
            k++;
        }
        XMLByteOutputStream xbos = new XMLByteOutputStream(xm.getUpdatedDocumentSize());
        xm.output(xbos);
        System.out.println(new String(xbos.getXML(),"UTF-16"));
    }