2017-08-02 74 views
1

我想創建一個這種形狀的xml,我將內部元素/a/b插入一個循環中,並設置元素b上的屬性。如何以編程方式使用VTD-XML創建xml?

<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

我想我可能知道你在做什麼。有幾個暗示

  • 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")); 
    } 
+0

只要文檔具有固定的大小,它就可以工作。我可以使用vtd-xml添加基於ia和sa之前未知大小的元素'/ a/b'嗎?或者,我應該不使用vtd-xml作爲這個用例,並通過字符串連接創建整個文檔,即stringbuffer start root標籤元素,在一個循環中追加具有屬性的'/ a/b'元素,並最終確定stringbuffer在循環之外關閉根標籤元素。 – mrt181

+1

這是一個偏好問題...連接字符串在我看來是創建XML文檔的最直觀的方式......並且您完全控制了所有內容......並且它並不難...... –