【问题标题】:write, update and save a well-formed xml file in as3在 as3 中写入、更新和保存格式良好的 xml 文件
【发布时间】:2012-06-18 23:58:05
【问题描述】:

我正在尝试更新 xml 文件和 save 元素 inside 已保存的根元素。

我只找到了 xml 文件刚刚打开而不保存的示例。有人可以帮我找到保存结果的最佳方法吗?

我现在的项目是这样的:

我正在通过 URLLoader/URLRequest 加载一个 xml 文件,并在几个文本字段中显示内容。来自输入字段的新文本通过 FileStream 直接保存(附加)到 applicationStorageDirectory 中的 xml 文件(将在 iPhone 上)。

然后应该将新输入添加到屏幕列表(使用 for 循环创建)并显示出来,但是,它不能做到那么远。从 xml 文件中读取新保存的输入后,我自然会收到错误 1088,因为 xml 文件格式不再正确。

这是因为输入附加在根元素之后,结果如下所示:

<root>
  <message></message>
  <date></date>
</root>
  <message>new input</message>
  <date></date>

当然,我想要的是这样的:

<root>
  <message></message>
  <date></date>
  <message>new input</message>
  <date></date>
</root>

但我不知道如何才能做到这一点。

我做了几次尝试来避免附加,比如加载 xml 内容,更改它,然后重新编写所有内容。但由于我还是 as3 的新手,我无法让它工作。

如果有人能告诉我最好的方法是什么以及如何解决它,那就太好了。

【问题讨论】:

  • 实际上我自己也做过几次,当您克服任何小的技术障碍时,唯一的主要问题是处理适当的类型转换。与我一起工作的一个家伙实际上为 AS3 对象编写了一个强大的 XML 读取器/写入器,但由于它是在工作时间完成的,我认为我们不允许提供该源(肯定至少必须与他核实。我'我已经亲自完成了你所说的两种方法,即加载 XML 然后替换部分,或者只是生成所有 XML。我认为后者是一个更好的选择。
  • 我将看看我是否可以从头开始尝试这个(至少 AS3 到 XML,反之可能需要一些时间),因为它对项目很有用我现在也在努力,这样我就可以发布源代码了。

标签: xml actionscript-3 flash actionscript filestream


【解决方案1】:

好吧,我只是想我会发布一个关于我目前所处位置的更新......

这应该能够为大多数对象输出 XML,到目前为止,如果您想开始尝试使用它进行调试,并且如果您有任何部分丢失或 XML 错误,请告诉我输出让我知道...我将继续并尝试使用解析器来反转该版本生成的 XML 的过程,当我这样做时可能会改变。

package
{
    import flash.utils.describeType;

    import mx.collections.IList;

    public class AS3ToXMLMapper
    {

        public function AS3ToXMLMapper()
        {
        }

        public static function generateXML(objectToMap:Object, basePropertyName:String="root"):String
        {
            var describeXML:XML = describeType(objectToMap);

            var xmlOutput:String = "<"+basePropertyName+" name=\""+describeXML.@name+"\" base=\""+describeXML.@base+"\">\n";

            if(describeXML.@isDynamic=="true")
            {
                for(var property:String in objectToMap)
                {
                    xmlOutput += "<"+property+">";
                    xmlOutput += objectToMap[property];
                    xmlOutput += "</"+property+">";
                }
            }
            else if(objectToMap is XML)
            {
                xmlOutput+=(objectToMap as XML).toString();
            }
            else if(objectToMap is XMLList)
            {
                xmlOutput+=(objectToMap as XMLList).toString();
            }
            else
            {
                for each(var accessor:XML in describeXML..accessor)
                {
                    xmlOutput+="\t"+exportProperty(objectToMap, accessor,true);
                }
                for each(var variable:XML in describeXML..variable)
                {
                    xmlOutput+="\t"+exportProperty(objectToMap, variable, false);
                }
            }

            xmlOutput += "</"+basePropertyName+">\n";
            trace(xmlOutput);
            return xmlOutput;
        }

        private static function exportProperty(objectToMap:Object, xmlObj:XML, isAccessor:Boolean):String
        {
            var xmlOutput:String="";
            var propName:String = xmlObj.@name.toString();
            var objectValue:Object = objectToMap[propName];
            if(!objectValue)
            {
                xmlOutput += "<"+propName+">";
                xmlOutput += "</"+propName+">";
                return xmlOutput;
            }

            if(isAccessor && xmlObj.@access != "readwrite")
            {
                return "";
            }
            if(objectValue is Array)
            {
                return exportArray(objectValue as Array, xmlObj.@name);
            }
            else if(objectValue is IList)
            {
                return exportArray((objectValue as IList).toArray(), propName);
            }
            else if(objectValue is int || objectValue is Number || objectValue is String || objectValue is uint || objectValue is Boolean)
            {
                xmlOutput += "<"+propName+" type=\""+xmlObj.@type+"\">";

                xmlOutput += objectValue;
                xmlOutput += "</"+propName+">"; 
            }
            else
            {
                return generateXML(objectValue, propName);
            }
            return xmlOutput;
        }

        private static function exportArray(array:Array, arrayName:String):String
        {
            var xmlOutput:String = "<"+arrayName+">\n";

            for each(var element:Object in array)
            {
                xmlOutput+="\t"+generateXML(element,"arrayElement");
            }

            xmlOutput += "</"+arrayName+">\n";
            return xmlOutput;
        }
    }
}

用法如下:

            var fs:FileStream = new FileStream();
            fs.open(new File("C:\\test.xml"),FileMode.WRITE);
            var thingToExport:Object = {aProperty:"someValue"};
            var as3XMLMapper:String = AS3ToXMLMapper.generateXML(thingToExport);
            fs.writeUTFBytes(as3XMLMapper);
            fs.close();

【讨论】:

  • 哇,非常感谢您的详尽回答。正如我所说,我是 as3 的新手,所以我仍在尝试弄清楚如何使用您的代码。我想这是覆盖整个 xml 的最佳方式。但是,当我覆盖旧文本时,如何先阅读它并将其与新文本结合?有没有办法加载旧文本并删除旧的根标签?我尝试使用 filestream.position 元素执行此操作,但它不起作用。
  • @MADMAX 没问题。基本上要使用它,您应该能够将第一个 sn-p 复制粘贴为它自己的类,然后第二个 sn-p 是从 AIR 桌面应用程序中使用的(唯一重要的原因是它使您可以访问 FileStream 类用于在不提示用户的情况下编写。您可以在任何其他 Flex 上下文中使用它,只需使用返回字符串的 AS3ToXMLMapper.generateXML(thingToExport),以测试您是否可以跟踪字符串。
  • 使用 filestream.position 您可以在字节流“数组”中向前或向后移动“字节光标”。每当您在字节数组缓冲区类型对象上使用读取方法时,它都会向前移动位置。 IMO 最好的选择是使用 readUTFBytes ,它将数据作为字符串返回,然后如果你想走那条路线,就操纵字符串。最终,尽管我认为最好生成整个 XML。当我过去这样做时,我会创建一个“模型”对象,在适当的时候保存它并在启动时加载它,这样可以保留值而无需分段解析。
  • 是的,我想做的是读取XML,转到之前的位置,然后从那里继续写入。对我来说听起来像是最快的解决方案,但是,我无法让它发挥作用。我现在将尝试实施您的方法。
【解决方案2】:

简单地使用 XML 文字不是更好吗?

package
{
  import flash.display.Sprite;

  public class ZutAlors extends Sprite
  {
    public function ZutAlors()
    {
      trace(messagesToXMLString('hello world'.split(' ')));
    }

    private function messageToXML(m:String, d:Date = null):XMLList
    {
      return <ret>
        <message>{m}</message>
        <date>{(d || new Date()).toString()}</date>
      </ret>.children();
    }

    private function messagesToXMLString(array:Array):XML
    {
      const ret:XML = <root />
      for each(var s:String in array)
      {
        ret.appendChild(messageToXML(s));
      }
      return ret;
    }
  }
}

如果 XML 格式不正确,则会出现编译错误...

【讨论】:

    猜你喜欢
    • 2012-02-03
    • 2016-07-05
    • 1970-01-01
    • 2012-06-04
    • 1970-01-01
    • 2022-01-24
    • 2020-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多