2011-12-27 44 views
0

我有了這個源XML:如何從另一個XML序列化XML在Android的改變層次

<source> 
<category id="1" /> 
<item1 /> 
<item2 /> 
<category id="2"/> 
<item1 /> 
<item2 /> 
</source> 

正如你所看到的所有項具有相同的層次結構。 我需要「翻譯」 /它序列化到這樣的另一個XML:

<source> 
    <category id="1"> 
    <item1 /> 
    <item2 /> 
    </category> 
    <category id="2"> 
     <item1 /> 
     <item2 /> 
    </category> 
</source> 

其中,「項目」是的「類別」的孩子。

我使用在Android工具XmlPullParser和XmlSerializer的,但我不介意使用另一個,如果他們與Android環境

的Tx

+0

我讀書各地。可能是XSLT的答案? – butelo 2011-12-27 19:46:56

回答

0

兼容爲便於XML格式,這不應該是硬。

一種可能的方法來讀取SAX解析器第一個XML文件是:

public class MySaxHandler extends DefaultHandler { 
    private List<Category> items = new LinkedList<Category>(); 
    private Category currentCategory; 
    public void startElement(String uri, String localName, String qName, Attributes attributes) { 
    if (localName.equals("category")) { 
     currentCategory = new Category(attributes.getValue("id")); 
     items.add(currentCategory); 
    } 
    if (localName.equals("item1") { 
     currentCategory.setItem1(new Item1(...)); 
    } 
    if (localName.equals("item2") { 
     currentCategory.setItem2(new Item2(...)); 
    } 
    } 
} 

對於每個<category>標籤創建一個新的Category對象。以下項目將被添加到最後一個類別對象。在閱讀內容時,您將創建稍後需要的層次結構(項目將添加到適當的類別中)。 它應該很容易將這一代碼,而不是使用SAX解析器XmlPullParser。我只是用薩克斯因爲我更熟悉它。

當你讀完你需要你的層次寫到一個新文件的第一個文件。

你可以在這樣的方式做到這一點:

StringBuilder b = new StringBuilder(); 
for (int i = 0; i < categories.size(); i++) { 
    b.append(categories.get(i).getXml()); 
} 
// write content of b into file 

getXml()爲每個類別可能看起來像:

public String getXml() { 
    StringBuilder b = new StringBuilder(); 
    b.append("<category id=\"" + this.id + "\">"); 
    for (int i = 0; i < items.size(); i++) { 
    b.append(items.get(i).getXml()); 
    } 
    b.append("</category>"); 
    return b.toString(); 
} 

每個項目在其getXml()方法創建自己的XML可能是

public String getXml() { 
    return "<item1 />"; 
} 

在最簡單的情況。

請注意用手該建築物XML只適合,如果你的XML結構保持簡單。如果結構變得越來越複雜,您應該使用一些適用於Android的輕量級xml庫(如xstream)。

+0

它應該工作。但是你必須將所有信息加載到內存中。我的想法是以「流式」的方式做到這一點。我的意思是讀取數據並一步完成。 – butelo 2011-12-28 08:14:30

+0

但是因爲我沒有明確指定它,我會檢查你的答案是否正確,因爲它當然是。謝謝。 – butelo 2011-12-28 08:21:07

1

我發現使用XSLT另一種方式: 這樣,我們使用XML-只有特定的工具,而不使用對象處理任何數據轉換。

創建transform.xsl文件來處理轉型:

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" encoding="UTF-8" /> 
    <xsl:strip-space elements="*" /> 
    <xsl:template match="/"> 
     <xsl:apply-templates /> 
    </xsl:template> 
    <xsl:template match="source"> 
     <source> 
      <xsl:apply-templates select="category" /> 
     </source> 
    </xsl:template> 
    <xsl:template match="category"> 
     <xsl:variable name="place" select="count(preceding-sibling::category)" /> 
     <category> 
      <xsl:attribute name="id"> 
    <xsl:value-of select="@id" /> 
    </xsl:attribute> 
      <xsl:apply-templates select="following-sibling::*[not(self::category)]"> 
       <xsl:with-param name="slot" select="$place" /> 
      </xsl:apply-templates> 
     </category> 
    </xsl:template> 
    <xsl:template match="item1"> 
     <xsl:param name="slot" /> 
     <xsl:choose> 
      <xsl:when test="count(preceding-sibling::category) = $slot + 1"> 
       <xsl:copy-of select="." /> 
      </xsl:when> 
      <xsl:otherwise /> 
     </xsl:choose> 
    </xsl:template> 
    <xsl:template match="item2"> 
     <xsl:param name="slot" /> 
     <xsl:choose> 
      <xsl:when test="count(preceding-sibling::category) = $slot + 1"> 
       <xsl:copy-of select="." /> 
      </xsl:when> 
      <xsl:otherwise /> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

,然後編寫代碼來處理轉型與所需的輸出data.xml中

  AssetManager am = getAssets(); 
     xml = am.open("source.xml"); 
     xsl = am.open("transform.xsl"); 

     Source xmlSource = new StreamSource(xml); 
     Source xsltSource = new StreamSource(xsl); 

     TransformerFactory transFact = TransformerFactory.newInstance(); 
     Transformer trans = transFact.newTransformer(xsltSource); 


     File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/data.xml"); 
     StreamResult result = new StreamResult(f); 
     trans.transform(xmlSource, result); 

而且其完成的文件。 更多的信息在這裏: http://www.dpawson.co.uk/xsl/sect2/flatfile.html