Как сериализовать XML в Android из другой меняющейся иерархии XML - PullRequest
0 голосов
/ 27 декабря 2011

У меня есть этот источник 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>

Где «items» являются потомками «category».Инструменты Android, но я не против использовать другие, если они совместимы со средой Android

Tx

Ответы [ 2 ]

1 голос
/ 28 декабря 2011

Я нашел другой способ использования 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>

А затем напишите код для обработки преобразования в файл с желаемыми выходными данными. 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

0 голосов
/ 28 декабря 2011

Для простого формата XML это не должно быть так сложно.

Возможный способ чтения первого 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 вместо синтаксического анализатора саксофона. Я просто использовал саксофон, потому что я более знаком с ним.

Когда вы закончите читать первый файл, вам нужно записать свою иерархию в новый файл.

Вы можете сделать это следующим образом:

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 остается такой простой. Если структура усложняется, вам следует использовать несколько облегченных библиотек xml, работающих на Android (например, xstream ).

...