public static Boolean IsDataEligible(MetaDataIO meta) { if (meta.Title.Length > 0) { return(true); } if (meta.Artist.Length > 0) { return(true); } if (meta.Comment.Length > 0) { return(true); } if (meta.Genre.Length > 0) { return(true); } if (meta.Copyright.Length > 0) { return(true); } foreach (var key in meta.AdditionalFields.Keys) { if (key.StartsWith("info.")) { return(true); } } return(false); }
public static void FromStream(Stream source, MetaDataIO meta, ReadTagParams readTagParams, uint chunkSize) { long position = source.Position; long initialPos = position; string key, value; int size; byte[] data = new byte[chunkSize]; while (source.Position < initialPos + chunkSize - 4) // 4 being the "INFO" purpose that belongs to the chunk { // Key source.Read(data, 0, 4); key = Utils.Latin1Encoding.GetString(data, 0, 4); // Size source.Read(data, 0, 4); size = StreamUtils.DecodeInt32(data); if (size > 0) { source.Read(data, 0, size); // Manage parasite zeroes at the end of data if (source.ReadByte() != 0) { source.Seek(-1, SeekOrigin.Current); } value = Utils.Latin1Encoding.GetString(data, 0, size); meta.SetMetaField("info." + key, Utils.StripEndingZeroChars(value), readTagParams.ReadAllMetaFrames); } } }
public static void FromStream(Stream source, MetaDataIO meta, ReadTagParams readTagParams, UInt32 chunkSize) { var position = source.Position; var initialPos = position; String key, value; Int32 size; var data = new Byte[256]; while (source.Position < initialPos + chunkSize - 4) // 4 being the "INFO" purpose that belongs to the chunk { // Key source.Read(data, 0, 4); key = Utils.Latin1Encoding.GetString(data, 0, 4); // Size source.Read(data, 0, 4); size = StreamUtils.DecodeInt32(data); // Value value = StreamUtils.ReadNullTerminatedString(source, Utils.Latin1Encoding); if (value.Length > 0) { meta.SetMetaField("info." + key, value, readTagParams.ReadAllMetaFrames); } position = source.Position; } }
public static void FromStream(Stream source, MetaDataIO meta, ReadTagParams readTagParams, uint chunkSize) { long position = source.Position; long initialPos = position; string key, value; int size; byte[] data = new byte[chunkSize]; long maxPos = initialPos + chunkSize - 4; // 4 being the "INFO" purpose that belongs to the chunk while (source.Position < maxPos) { // Key source.Read(data, 0, 4); key = Utils.Latin1Encoding.GetString(data, 0, 4); // Size source.Read(data, 0, 4); size = StreamUtils.DecodeInt32(data); // Do _NOT_ use StreamUtils.ReadNullTerminatedString because non-textual fields may be found here (e.g. NITR) if (size > 0) { source.Read(data, 0, size); // Manage parasite zeroes at the end of data if (source.Position < maxPos && source.ReadByte() != 0) { source.Seek(-1, SeekOrigin.Current); } value = Utils.Latin1Encoding.GetString(data, 0, size); meta.SetMetaField("info." + key, Utils.StripEndingZeroChars(value), readTagParams.ReadAllMetaFrames); } } }
private static int readInt32(Stream source, MetaDataIO meta, string fieldName, byte[] buffer, bool readAllMetaFrames) { source.Read(buffer, 0, 4); int value = StreamUtils.DecodeInt32(buffer); meta.SetMetaField(fieldName, value.ToString(), readAllMetaFrames); return(value); }
public static void FromStream(Stream source, MetaDataIO meta, ReadTagParams readTagParams, uint chunkSize) { IList <string> position = new List <string>(); bool inList = false; int listDepth = 0; int listCounter = 1; position.Add("ixml"); using (MemoryStream mem = new MemoryStream((int)chunkSize)) { StreamUtils.CopyStream(source, mem, (int)chunkSize); // Isolate XML structure in a clean memory chunk mem.Seek(0, SeekOrigin.Begin); using (XmlReader reader = XmlReader.Create(mem)) { while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: // Element start string key = reader.Name; if (inList && reader.Depth == listDepth + 1 && !key.EndsWith("COUNT", StringComparison.OrdinalIgnoreCase)) { key = key + "[" + listCounter + "]"; listCounter++; } if (!key.Equals("BWFXML", StringComparison.OrdinalIgnoreCase)) { position.Add(key); } if (!inList && reader.Name.EndsWith("LIST", StringComparison.OrdinalIgnoreCase)) { inList = true; listDepth = reader.Depth; listCounter = 1; } break; case XmlNodeType.Text: if (reader.Value != null && reader.Value.Length > 0) { meta.SetMetaField(getPosition(position), reader.Value, readTagParams.ReadAllMetaFrames); } break; case XmlNodeType.EndElement: // Element end position.RemoveAt(position.Count - 1); if (inList && reader.Name.EndsWith("LIST", StringComparison.OrdinalIgnoreCase)) { inList = false; } break; } } } } }
public static bool IsDataEligible(MetaDataIO meta) { foreach (string key in meta.AdditionalFields.Keys) { if (key.StartsWith("ixml.")) { return(true); } } return(false); }
public static bool IsDataEligible(MetaDataIO meta) { if (meta.GeneralDescription.Length > 0) { return(true); } foreach (string key in meta.AdditionalFields.Keys) { if (key.StartsWith("bext.")) { return(true); } } return(false); }
public static Int32 ToStream(BinaryWriter w, Boolean isLittleEndian, MetaDataIO meta) { var additionalFields = meta.AdditionalFields; w.Write(Utils.Latin1Encoding.GetBytes(CHUNK_LIST)); var sizePos = w.BaseStream.Position; w.Write((Int32)0); // Placeholder for chunk size that will be rewritten at the end of the method w.Write(Utils.Latin1Encoding.GetBytes(PURPOSE_INFO)); // 'Classic' fields (NB : usually done within a loop by accessing MetaDataIO.tagData) IDictionary <String, String> writtenFields = new Dictionary <String, String>(); // Title var value = Utils.ProtectValue(meta.Title); if (0 == value.Length && additionalFields.Keys.Contains("info.INAM")) { value = additionalFields["info.INAM"]; } if (value.Length > 0) { writeSizeAndNullTerminatedString("INAM", value, w, writtenFields); } // Artist value = Utils.ProtectValue(meta.Artist); if (0 == value.Length && additionalFields.Keys.Contains("info.IART")) { value = additionalFields["info.IART"]; } if (value.Length > 0) { writeSizeAndNullTerminatedString("IART", value, w, writtenFields); } // Copyright value = Utils.ProtectValue(meta.Copyright); if (0 == value.Length && additionalFields.Keys.Contains("info.ICOP")) { value = additionalFields["info.ICOP"]; } if (value.Length > 0) { writeSizeAndNullTerminatedString("ICOP", value, w, writtenFields); } // Genre value = Utils.ProtectValue(meta.Genre); if (0 == value.Length && additionalFields.Keys.Contains("info.IGNR")) { value = additionalFields["info.IGNR"]; } if (value.Length > 0) { writeSizeAndNullTerminatedString("IGNR", value, w, writtenFields); } // Comment value = Utils.ProtectValue(meta.Comment); if (0 == value.Length && additionalFields.Keys.Contains("info.ICMT")) { value = additionalFields["info.ICMT"]; } if (value.Length > 0) { writeSizeAndNullTerminatedString("ICMT", value, w, writtenFields); } String shortKey; foreach (var key in additionalFields.Keys) { if (key.StartsWith("info.")) { shortKey = key.Substring(5, key.Length - 5).ToUpper(); if (!writtenFields.ContainsKey(key)) { if (additionalFields[key].Length > 0) { writeSizeAndNullTerminatedString(shortKey, additionalFields[key], w, writtenFields); } } } } var finalPos = w.BaseStream.Position; w.BaseStream.Seek(sizePos, SeekOrigin.Begin); if (isLittleEndian) { w.Write((Int32)(finalPos - sizePos - 4)); } else { w.Write(StreamUtils.EncodeBEInt32((Int32)(finalPos - sizePos - 4))); } return(14); }
public static int ToStream(BinaryWriter w, bool isLittleEndian, MetaDataIO meta) { IDictionary <string, string> additionalFields = meta.AdditionalFields; w.Write(Utils.Latin1Encoding.GetBytes(CHUNK_IXML)); long sizePos = w.BaseStream.Position; w.Write(0); // Placeholder for chunk size that will be rewritten at the end of the method XmlWriterSettings settings = new XmlWriterSettings(); settings.CloseOutput = false; settings.Encoding = Encoding.UTF8; XmlWriter writer = XmlWriter.Create(w.BaseStream, settings); //writer.Formatting = Formatting.None; writer.WriteStartDocument(); writer.WriteStartElement("BWFXML"); string[] path; string[] previousPath = null; bool first = true; string subkey; foreach (string key in additionalFields.Keys) { if (key.StartsWith("ixml.")) { path = key.Split('.'); if (first) { previousPath = path; first = false; } // Closes all terminated paths for (int i = previousPath.Length - 2; i >= 0; i--) { if ((path.Length <= i) || (path.Length > i && !path[i].Equals(previousPath[i]))) { writer.WriteEndElement(); } } // Opens all new paths for (int i = 0; i < path.Length - 1; i++) { if (previousPath.Length <= i || !path[i].Equals(previousPath[i])) { subkey = path[i]; if (subkey.Contains("[")) { subkey = subkey.Substring(0, subkey.IndexOf("[")); // Remove [x]'s } writer.WriteStartElement(subkey.ToUpper()); } } writer.WriteElementString(path[path.Length - 1], additionalFields[key]); previousPath = path; } } // Closes all terminated paths if (previousPath != null) { for (int i = previousPath.Length - 2; i >= 0; i--) { writer.WriteEndElement(); } } writer.Close(); long finalPos = w.BaseStream.Position; w.BaseStream.Seek(sizePos, SeekOrigin.Begin); if (isLittleEndian) { w.Write((int)(finalPos - sizePos - 4)); } else { w.Write(StreamUtils.EncodeBEInt32((int)(finalPos - sizePos - 4))); } return(14); }
public static int ToStream(BinaryWriter w, bool isLittleEndian, MetaDataIO meta) { IDictionary <string, string> additionalFields = meta.AdditionalFields; w.Write(Utils.Latin1Encoding.GetBytes(CHUNK_BEXT)); long sizePos = w.BaseStream.Position; w.Write((int)0); // Placeholder for chunk size that will be rewritten at the end of the method // Text values string description = Utils.ProtectValue(meta.GeneralDescription); if (0 == description.Length && additionalFields.Keys.Contains("bext.description")) { description = additionalFields["bext.description"]; } writeFixedTextValue(description, 256, w); writeFixedFieldTextValue("bext.originator", 32, additionalFields, w); writeFixedFieldTextValue("bext.originatorReference", 32, additionalFields, w); writeFixedFieldTextValue("bext.originationDate", 10, additionalFields, w); writeFixedFieldTextValue("bext.originationTime", 8, additionalFields, w); // Int values writeFieldIntValue("bext.timeReference", additionalFields, w, (ulong)0); writeFieldIntValue("bext.version", additionalFields, w, (ushort)0); // UMID if (additionalFields.Keys.Contains("bext.UMID")) { if (Utils.IsHex(additionalFields["bext.UMID"])) { int usedValues = (int)Math.Floor(additionalFields["bext.UMID"].Length / 2.0); for (int i = 0; i < usedValues; i++) { w.Write(Convert.ToByte(additionalFields["bext.UMID"].Substring(i * 2, 2), 16)); } // Complete the field to 64 bytes for (int i = 0; i < 64 - usedValues; i++) { w.Write((byte)0); } } else { LogDelegator.GetLogDelegate()(Log.LV_WARNING, "'bext.UMID' : error writing field - hexadecimal notation required; " + additionalFields["bext.UMID"] + " found"); for (int i = 0; i < 64; i++) { w.Write((byte)0); } } } else { for (int i = 0; i < 64; i++) { w.Write((byte)0); } } // Float values writeField100DecimalValue("bext.loudnessValue", additionalFields, w, (short)0); writeField100DecimalValue("bext.loudnessRange", additionalFields, w, (short)0); writeField100DecimalValue("bext.maxTruePeakLevel", additionalFields, w, (short)0); writeField100DecimalValue("bext.maxMomentaryLoudness", additionalFields, w, (short)0); writeField100DecimalValue("bext.maxShortTermLoudness", additionalFields, w, (short)0); // Reserved for (int i = 0; i < 180; i++) { w.Write((byte)0); } // CodingHistory byte[] textData = new byte[0]; if (additionalFields.Keys.Contains("bext.codingHistory")) { textData = Utils.Latin1Encoding.GetBytes(additionalFields["bext.codingHistory"]); w.Write(textData); } w.Write(new byte[2] { 13, 10 } /* CR LF */); // Emulation of the BWFMetaEdit padding behaviour (256 characters) for (int i = 0; i < 256 - ((textData.Length + 2) % 256); i++) { w.Write((byte)0); } long finalPos = w.BaseStream.Position; w.BaseStream.Seek(sizePos, SeekOrigin.Begin); if (isLittleEndian) { w.Write((int)(finalPos - sizePos - 4)); } else { w.Write(StreamUtils.EncodeBEInt32((int)(finalPos - sizePos - 4))); } return(14); }
public static void FromStream(Stream source, MetaDataIO meta, ReadTagParams readTagParams) { string str; byte[] data = new byte[256]; // Description source.Read(data, 0, 256); str = Utils.StripEndingZeroChars(Utils.Latin1Encoding.GetString(data).Trim()); if (str.Length > 0) { meta.SetMetaField("bext.description", str, readTagParams.ReadAllMetaFrames); } // Originator source.Read(data, 0, 32); str = Utils.StripEndingZeroChars(Utils.Latin1Encoding.GetString(data, 0, 32).Trim()); if (str.Length > 0) { meta.SetMetaField("bext.originator", str, readTagParams.ReadAllMetaFrames); } // OriginatorReference source.Read(data, 0, 32); str = Utils.StripEndingZeroChars(Utils.Latin1Encoding.GetString(data, 0, 32).Trim()); if (str.Length > 0) { meta.SetMetaField("bext.originatorReference", str, readTagParams.ReadAllMetaFrames); } // OriginationDate source.Read(data, 0, 10); str = Utils.StripEndingZeroChars(Utils.Latin1Encoding.GetString(data, 0, 10).Trim()); if (str.Length > 0) { meta.SetMetaField("bext.originationDate", str, readTagParams.ReadAllMetaFrames); } // OriginationTime source.Read(data, 0, 8); str = Utils.StripEndingZeroChars(Utils.Latin1Encoding.GetString(data, 0, 8).Trim()); if (str.Length > 0) { meta.SetMetaField("bext.originationTime", str, readTagParams.ReadAllMetaFrames); } // TimeReference source.Read(data, 0, 8); ulong timeReference = StreamUtils.DecodeUInt64(data); meta.SetMetaField("bext.timeReference", timeReference.ToString(), readTagParams.ReadAllMetaFrames); // BEXT version source.Read(data, 0, 2); int intData = StreamUtils.DecodeUInt16(data); meta.SetMetaField("bext.version", intData.ToString(), readTagParams.ReadAllMetaFrames); // UMID source.Read(data, 0, 64); str = ""; int usefulLength = 32; // "basic" UMID if (data[12] > 19) { usefulLength = 64; // data[12] gives the size of remaining UMID } for (int i = 0; i < usefulLength; i++) { str = str + data[i].ToString("X2"); } meta.SetMetaField("bext.UMID", str, readTagParams.ReadAllMetaFrames); // LoudnessValue source.Read(data, 0, 2); intData = StreamUtils.DecodeInt16(data); meta.SetMetaField("bext.loudnessValue", (intData / 100.0).ToString(), readTagParams.ReadAllMetaFrames); // LoudnessRange source.Read(data, 0, 2); intData = StreamUtils.DecodeInt16(data); meta.SetMetaField("bext.loudnessRange", (intData / 100.0).ToString(), readTagParams.ReadAllMetaFrames); // MaxTruePeakLevel source.Read(data, 0, 2); intData = StreamUtils.DecodeInt16(data); meta.SetMetaField("bext.maxTruePeakLevel", (intData / 100.0).ToString(), readTagParams.ReadAllMetaFrames); // MaxMomentaryLoudness source.Read(data, 0, 2); intData = StreamUtils.DecodeInt16(data); meta.SetMetaField("bext.maxMomentaryLoudness", (intData / 100.0).ToString(), readTagParams.ReadAllMetaFrames); // MaxShortTermLoudness source.Read(data, 0, 2); intData = StreamUtils.DecodeInt16(data); meta.SetMetaField("bext.maxShortTermLoudness", (intData / 100.0).ToString(), readTagParams.ReadAllMetaFrames); // Reserved source.Seek(180, SeekOrigin.Current); // CodingHistory long initialPos = source.Position; if (StreamUtils.FindSequence(source, new byte[2] { 13, 10 } /* CR LF */)) { long endPos = source.Position - 2; source.Seek(initialPos, SeekOrigin.Begin); if (data.Length < (int)(endPos - initialPos)) { data = new byte[(int)(endPos - initialPos)]; } source.Read(data, 0, (int)(endPos - initialPos)); str = Utils.StripEndingZeroChars(Utils.Latin1Encoding.GetString(data, 0, (int)(endPos - initialPos)).Trim()); if (str.Length > 0) { meta.SetMetaField("bext.codingHistory", str, readTagParams.ReadAllMetaFrames); } } }
public static void FromStream(Stream source, MetaDataIO meta, ReadTagParams readTagParams) { string str; byte[] data = new byte[256]; // Manufacturer readInt32(source, meta, "sample.manufacturer", data, readTagParams.ReadAllMetaFrames); // Product readInt32(source, meta, "sample.product", data, readTagParams.ReadAllMetaFrames); // Period readInt32(source, meta, "sample.period", data, readTagParams.ReadAllMetaFrames); // MIDI unity note readInt32(source, meta, "sample.MIDIUnityNote", data, readTagParams.ReadAllMetaFrames); // MIDI pitch fraction readInt32(source, meta, "sample.MIDIPitchFraction", data, readTagParams.ReadAllMetaFrames); // SMPTE format readInt32(source, meta, "sample.SMPTEFormat", data, readTagParams.ReadAllMetaFrames); // SMPTE offsets source.Read(data, 0, 1); sbyte sByteData = StreamUtils.DecodeSignedByte(data); meta.SetMetaField("sample.SMPTEOffset.Hours", sByteData.ToString(), readTagParams.ReadAllMetaFrames); source.Read(data, 0, 1); byte byteData = StreamUtils.DecodeUByte(data); meta.SetMetaField("sample.SMPTEOffset.Minutes", byteData.ToString(), readTagParams.ReadAllMetaFrames); source.Read(data, 0, 1); byteData = StreamUtils.DecodeUByte(data); meta.SetMetaField("sample.SMPTEOffset.Seconds", byteData.ToString(), readTagParams.ReadAllMetaFrames); source.Read(data, 0, 1); byteData = StreamUtils.DecodeUByte(data); meta.SetMetaField("sample.SMPTEOffset.Frames", byteData.ToString(), readTagParams.ReadAllMetaFrames); // Num sample loops int numSampleLoops = readInt32(source, meta, "sample.NumSampleLoops", data, readTagParams.ReadAllMetaFrames); // Sample loops size (not useful here) source.Seek(4, SeekOrigin.Current); for (int i = 0; i < numSampleLoops; i++) { // Cue point ID readInt32(source, meta, "sample.SampleLoop[" + i + "].CuePointId", data, readTagParams.ReadAllMetaFrames); // Type readInt32(source, meta, "sample.SampleLoop[" + i + "].Type", data, readTagParams.ReadAllMetaFrames); // Start readInt32(source, meta, "sample.SampleLoop[" + i + "].Start", data, readTagParams.ReadAllMetaFrames); // End readInt32(source, meta, "sample.SampleLoop[" + i + "].End", data, readTagParams.ReadAllMetaFrames); // Fraction readInt32(source, meta, "sample.SampleLoop[" + i + "].Fraction", data, readTagParams.ReadAllMetaFrames); // Play count readInt32(source, meta, "sample.SampleLoop[" + i + "].PlayCount", data, readTagParams.ReadAllMetaFrames); } }
public static int ToStream(BinaryWriter w, bool isLittleEndian, MetaDataIO meta) { IDictionary <string, string> additionalFields = meta.AdditionalFields; w.Write(Utils.Latin1Encoding.GetBytes(CHUNK_SAMPLE)); long sizePos = w.BaseStream.Position; w.Write(0); // Placeholder for chunk size that will be rewritten at the end of the method // Int values writeFieldIntValue("sample.manufacturer", additionalFields, w, 0); writeFieldIntValue("sample.product", additionalFields, w, 0); writeFieldIntValue("sample.period", additionalFields, w, 1); writeFieldIntValue("sample.MIDIUnityNote", additionalFields, w, 0); writeFieldIntValue("sample.MIDIPitchFraction", additionalFields, w, 0); writeFieldIntValue("sample.SMPTEFormat", additionalFields, w, 0); // SMPTE offset writeFieldIntValue("sample.SMPTEOffset.Hours", additionalFields, w, (sbyte)0); writeFieldIntValue("sample.SMPTEOffset.Minutes", additionalFields, w, (byte)0); writeFieldIntValue("sample.SMPTEOffset.Seconds", additionalFields, w, (byte)0); writeFieldIntValue("sample.SMPTEOffset.Frames", additionalFields, w, (byte)0); // == Sample loops // How many of them do we have ? -> count distinct indexes IList <string> keys = new List <string>(); foreach (string s in additionalFields.Keys) { if (s.StartsWith("sample.SampleLoop")) { string key = s.Substring(0, s.IndexOf("]") + 1); if (!keys.Contains(key)) { keys.Add(key); } } } w.Write(keys.Count); // Sample loops data size long sampleLoopsPos = w.BaseStream.Position; w.Write(0); // Placeholder for data size that will be rewritten at the end of the method // Sample loops data foreach (string key in keys) { writeFieldIntValue(key + ".CuePointId", additionalFields, w, 0); writeFieldIntValue(key + ".Type", additionalFields, w, 0); writeFieldIntValue(key + ".Start", additionalFields, w, 0); writeFieldIntValue(key + ".End", additionalFields, w, 0); writeFieldIntValue(key + ".Fraction", additionalFields, w, 0); writeFieldIntValue(key + ".PlayCount", additionalFields, w, 0); } // Write actual sample loops data size long finalPos = w.BaseStream.Position; w.BaseStream.Seek(sampleLoopsPos, SeekOrigin.Begin); w.Write((int)(finalPos - sampleLoopsPos - 4)); // Write actual tag size w.BaseStream.Seek(sizePos, SeekOrigin.Begin); if (isLittleEndian) { w.Write((int)(finalPos - sizePos - 4)); } else { w.Write(StreamUtils.EncodeBEInt32((int)(finalPos - sizePos - 4))); } return(10); }
public static int ToStream(BinaryWriter w, bool isLittleEndian, MetaDataIO meta) { IDictionary <string, string> additionalFields = meta.AdditionalFields; w.Write(Utils.Latin1Encoding.GetBytes(CHUNK_IXML)); long sizePos = w.BaseStream.Position; w.Write(0); // Placeholder for chunk size that will be rewritten at the end of the method XmlWriterSettings settings = new XmlWriterSettings(); settings.CloseOutput = false; settings.Encoding = Encoding.UTF8; XmlWriter writer = XmlWriter.Create(w.BaseStream, settings); //writer.Formatting = Formatting.None; writer.WriteStartDocument(); writer.WriteStartElement("BWFXML"); // Path notes : key = node path; value = node name Dictionary <string, string> pathNodes = new Dictionary <string, string>(); List <string> previousPathNodes = new List <string>(); string subkey; foreach (string key in additionalFields.Keys) { if (key.StartsWith("ixml.")) { // Create the list of path nodes List <string> singleNodes = new List <string>(key.Split('.')); singleNodes.RemoveAt(0); // Remove the "ixml" node StringBuilder nodePrefix = new StringBuilder(); pathNodes.Clear(); foreach (string nodeName in singleNodes) { nodePrefix.Append(".").Append(nodeName); pathNodes.Add(nodePrefix.ToString(), nodeName); } // Close all terminated (i.e. non present in current path) nodes in reverse order for (int i = previousPathNodes.Count - 2; i >= 0; i--) { if (!pathNodes.ContainsKey(previousPathNodes[i])) { writer.WriteEndElement(); } } // Opens all new (i.e. non present in previous path) nodes foreach (string nodePath in pathNodes.Keys) { if (!previousPathNodes.Contains(nodePath)) { subkey = pathNodes[nodePath]; if (subkey.Equals(singleNodes.Last())) { continue; // Last node is a leaf, not a node } if (subkey.Contains("[")) { subkey = subkey.Substring(0, subkey.IndexOf("[")); // Remove [x]'s } writer.WriteStartElement(subkey.ToUpper()); } } // Write the last node (=leaf) as a proper value writer.WriteElementString(singleNodes.Last(), additionalFields[key]); previousPathNodes = pathNodes.Keys.ToList(); } } // Closes all terminated paths if (previousPathNodes != null) { for (int i = previousPathNodes.Count - 2; i >= 0; i--) { writer.WriteEndElement(); } } writer.Close(); long finalPos = w.BaseStream.Position; w.BaseStream.Seek(sizePos, SeekOrigin.Begin); if (isLittleEndian) { w.Write((int)(finalPos - sizePos - 4)); } else { w.Write(StreamUtils.EncodeBEInt32((int)(finalPos - sizePos - 4))); } return(14); }