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

Java 如何使用VTD-xml以编程方式创建xml?,java,xml,vtd-xml,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>

我想创建一个具有此形状的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;
  }
publicstaticstringcreatexml(集合编号、集合词){
字符串charsetName=“UTF-16”;
byte[]root=”“.getBytes(charsetName);
VTDGen vg=新VTDGen();
自动驾驶仪ap=新自动驾驶仪();
ap.selectXPath(“/ROOT”);
XMLModifier xm=新的XMLModifier();
vg.setDoc(根);
解析(false);
VTDNav vn=vg.getNav();
ap.bind(vn);
xm.bind(vn);
字节[]aTag=“”.getBytes(charsetName);
byte[]bTag=”“.getBytes(charsetName);
int i;
字符串collect=numbers.stream().flatMap(number->words.stream().map(word->{
试一试{
xm.插入式后置(aTag);
ap.a.(“a”);
xm.插入式尾管(bTag);
ap.b;
xm.insertAttribute(字符串
.format(“attr1=\%d\”attr2=\%s\”,
数字,
),;
返回xm.outputandParse().toNormalizedString(0);
}捕获(ModifyException | NavException | ParseException | IOException | TranscodeException | XPathParseException e){
抛出新的运行时异常(e);
}
}))
.collect(收集器。连接(“”);
回款到付;
}
因为我给insertAfterHead打了两次电话,所以我得到了一份修改后的请柬。
如何生成所需的xml形状?我还不完全明白如何将偏移量放在正确的位置。

我想我可能知道您想要实现什么。有一些建议

  • selectXPath(a)只是将xpath编译为内部格式。。。它不会计算为您的节点集。要计算它,需要调用evalXPath()

  • 您希望在根节点下插入尽可能多的字符串作为单个字符串连接。实际上,字符串连接操作应该作为应用程序逻辑的独立部分进行。在VTD-XML中,您可以根据位字节、字节数组和int/long数组进行思考

下面是我对你的代码的修改

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"));
    }
publicstaticvoidmain(字符串[]args)抛出VTDException、IOException、,
不支持的编码异常{
字符串charsetName=“UTF-16”;
byte[]root=“”
.getBytes(charsetName);//这是您要开始使用的模板
VTDGen vg=新VTDGen();
自动驾驶仪ap=新自动驾驶仪();
ap.selectXPath(“/ROOT/a/b”);
XMLModifier xm=新的XMLModifier();
vg.setDoc(根);
解析(false);
VTDNav vn=vg.getNav();
ap.bind(vn);
xm.bind(vn);
int i=0;
int[]ia=新的int[4];
ia[0]=1;ia[1]=1;ia[2]=2;ia[3]=2;
字符串[]sa=新字符串[4];
sa[0]=“a”;sa[1]=“b”;sa[2]=“a”;sa[3]=“b”;
int k=0;
而((i=ap.evalXPath())!=-1){
xm.insertAttribute(String.format(“attr1=\%d\”attr2=\%s\”,
ia[k],
sa[k]);
k++;
}
xbos=新的XMLByteOutputStream(xm.getUpdatedDocumentSize());
xm.输出(xbos);
System.out.println(新字符串(xbos.getXML(),“UTF-16”);
}

只要文档的大小固定,此功能就可以工作。我是否可以使用vtd xml根据以前未知的ia和sa大小添加元素
/a/b
?或者我不应该在这个用例中使用vtd xml并通过字符串连接创建整个文档,也就是stringbuffer开始根标记元素,将
/a/b
元素与循环中的属性一起追加,并在循环外使用结束根标记元素完成stringbuffer。这是一个偏好问题。。。在我看来,串接字符串是创建XML文档最直观的方法。。。你可以完全控制一切。。。这一点也不难。。。