0

我有这个源xml:

<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 环境兼容,我不介意使用其他工具

发送

4

2 回答 2

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

于 2011-12-28T17:21:58.480 回答
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对象。以下项目将添加到最后一个类别对象。在阅读内容时,您会创建稍后需要的层次结构(项目被添加到适当的类别中)。转换此代码以使用 XmlPullParser 而不是 sax 解析器应该很容易。我只是使用萨克斯,因为我更熟悉它。

当你读完第一个文件后,你需要将你的层次结构写入一个新文件。

您可以通过以下方式执行此操作:

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();
}

每个项目在其方法中创建自己的 xml getXml(),可以是

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

在最简单的情况下。

请注意,仅当您的 xml 结构保持如此简单时,手动构建 xml 才适用。如果结构变得越来越复杂,您应该使用一些适用于 Android 的轻量级 xml 库(如xstream)。

于 2011-12-28T01:58:39.797 回答