Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/227.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在android中从另一个xml变化层次序列化xml_Android_Xslt_Xml Serialization_Xmlpullparser - Fatal编程技术网

如何在android中从另一个xml变化层次序列化xml

如何在android中从另一个xml变化层次序列化xml,android,xslt,xml-serialization,xmlpullparser,Android,Xslt,Xml Serialization,Xmlpullparser,我得到了这个源xml: <source> <category id="1" /> <item1 /> <item2 /> <category id="2"/> <item1 /> <item2 /> </source> 正如您所看到的,所有项目都具有相同的层次结构。 我需要将其“翻译”/序列化为另一个XML,如下所示: <source> <categor

我得到了这个源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>
StringBuilder b = new StringBuilder();
for (int i = 0; i < categories.size(); i++) {
  b.append(categories.get(i).getXml());
}
// write content of b into file

其中“项目”是“类别”的子项

我正在使用Android工具中的XmlPullParser和XmlSerializer,但如果它们与Android环境兼容,我不介意使用另一个


Tx

对于一种简单的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(...));
    }
  }
}
每个类别的
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只适用于xml结构保持简单的情况。如果结构变得越来越复杂,您应该使用一些在Android上工作的轻量级xml库(如)。

我找到了使用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>
一切都结束了。 更多信息请点击此处:

我到处都在读。XSLT可能是答案吗?它应该有效。但是你必须把所有的信息载入内存。我的想法是以“流”的方式来做。我的意思是一步读数据,一步构建。但由于我没有明确说明,我会检查你的答案是否正确,因为它当然是正确的。非常感谢。
<?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>
         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);