简体   繁体   English

如何从另一个更改层次结构的XML序列化android中的xml

[英]How to serialize xml in android from another xml changing hierarchy

I've got this source xml: 我有这个源XML:

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

As you can see all items have the same hierarchy. 如您所见,所有项目都具有相同的层次结构。 And I need to "translate"/serialize it to another XML like this: 我需要将其“翻译” /序列化为另一个XML,如下所示:

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

Where "items" are children of "category". 其中“项目”是“类别”的子级。

I'm using XmlPullParser and XmlSerializer from Android tools but I don't mind to use another if they are compatible with Android environment 我正在使用Android工具中的XmlPullParser和XmlSerializer,但如果它们与Android环境兼容,我不介意使用其他工具

Tx Tx

I've found another way using XSLT: This way we use XML-only specific tools for transform without handling any data with objects. 我发现了使用XSLT的另一种方式:这种方式我们使用仅XML的特定工具进行转换,而无需使用对象处理任何数据。

create a transform.xsl file to handle transformation: 创建一个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>

And then write the code to handle transformation to a file with desired output data.xml 然后编写代码以处理转换为具有所需输出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);

And its done. 它完成了。 more info here: http://www.dpawson.co.uk/xsl/sect2/flatfile.html 此处提供更多信息: http : //www.dpawson.co.uk/xsl/sect2/flatfile.html

For an easy xml format this shouldn't be that hard. 对于简单的xml格式,这并不难。

A possible way to read the first xml file with a sax parser would be: 使用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(...));
    }
  }
}

For each <category> tag you create a new Category object. 为每个<category>标签创建一个新的Category对象。 The following items will be added to the last category object. 以下项目将添加到最后一个类别对象。 While reading the contents you create the hierarchy you need later (items are added to the appropriate category). 阅读内容时,您将创建稍后需要的层次结构(将项目添加到适当的类别)。 It should be easy to transform this code to use XmlPullParser instead of sax parser. 转换此代码以使用XmlPullParser代替sax解析器应该很容易。 I just used sax because I am more familiar with it. 我只是使用了萨克斯,因为我对此比较熟悉。

When you finished reading the first file you need to write your hierarchy to a new file. 阅读完第一个文件后,需要将层次结构写入新文件。

You can do this in a way like this: 您可以按照以下方式进行操作:

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() for each category could look like: 每个类别的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();
}

Each item creates its own xml in its getXml() method which could be 每个项目都会在其getXml()方法中创建自己的xml,该方法可能是

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

in the easiest case. 在最简单的情况下。

Please note that building xml by hand is only suitable if you xml structure stays that simple. 请注意,只有在xml结构保持如此简单的情况下,手动构建xml才适用。 If the structure is becoming more complicated you should make use of some lightweight xml libraries that work on Android (like xstream ). 如果结构变得越来越复杂,则应使用一些可在Android上使用的轻量级xml库(例如xstream )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM