/// <summary> /// Reads all nodes in the binary XML. /// </summary> /// <returns>Returns the XML document.</returns> public XmlDocument Read() { while (true) { var nodeType = _nodeBuffer.ReadU8(); //Array flag is on the second bit var array = (nodeType & 64) > 0; nodeType = (byte)(nodeType & ~64); NodeType propertyType; if (Enum.IsDefined(typeof(ControlType), nodeType)) { switch ((ControlType)nodeType) { case ControlType.NodeStart: var newElement = _xmlDocument.CreateElement (_nodeBuffer.ReadString(), null); if (_currentElement != null) { _currentElement.AppendChild(newElement); } else { _xmlDocument.AppendChild(newElement); } _currentElement = newElement; break; case ControlType.Attribute: var value = _dataBuffer.ReadString(_dataBuffer.ReadS32()); _currentElement.SetAttribute(_nodeBuffer.ReadString(), value); break; case ControlType.NodeEnd: if (_currentElement.ParentNode is XmlDocument) { return(_xmlDocument); } _currentElement = (XmlElement)_currentElement.ParentNode; break; case ControlType.FileEnd: return(_xmlDocument); } } else if (TypeDictionary.TypeMap.TryGetValue(nodeType, out propertyType)) { var elementName = _nodeBuffer.ReadString(); _currentElement = (XmlElement)_currentElement.AppendChild(_xmlDocument.CreateElement(elementName)); var attribute = _xmlDocument.CreateAttribute("__type"); attribute.Value = propertyType.Name; _currentElement.Attributes.Append(attribute); var arraySize = propertyType.Size * propertyType.Count; if (array || propertyType.Name == "str" || propertyType.Name == "bin") { arraySize = _dataBuffer.ReadS32(); //Total size. } if (propertyType.Name == "str") { _currentElement.InnerText = _dataBuffer.ReadString(arraySize); } else if (propertyType.Name == "bin") { _currentElement.InnerText = _dataBuffer.ReadBinary(arraySize); _currentElement.SetAttribute("__size", arraySize.ToString()); } else { if (array) { var size = (arraySize / (propertyType.Size * propertyType.Count)).ToString(); _currentElement.SetAttribute("__count", size); } var buffer = _dataBuffer.ReadBytes(arraySize); var result = new List <string>(); for (var i = 0; i < arraySize / propertyType.Size; i++) { result.Add(propertyType.ToString(buffer.Skip(i * propertyType.Size) .Take(propertyType.Size).ToArray())); } _currentElement.InnerText = string.Join(" ", result); } } else { throw new KbinException($"Unknown node type: {nodeType}"); } } }
public byte[] ReadXmlByte() { string holdValue = null; while (true) { var nodeType = _nodeBuffer.ReadU8(); //Array flag is on the second bit var array = (nodeType & 0x40) > 0; nodeType = (byte)(nodeType & ~0x40); NodeType propertyType; if (_controlTypes.Contains(nodeType)) { switch ((ControlType)nodeType) { case ControlType.NodeStart: if (holdValue != null) { _xmlWriter.WriteString(holdValue); holdValue = null; } var elementName = _nodeBuffer.ReadString(); _xmlWriter.WriteStartElement(elementName); break; case ControlType.Attribute: var attr = _nodeBuffer.ReadString(); var value = _dataBuffer.ReadString(_dataBuffer.ReadS32()); _xmlWriter.WriteStartAttribute(attr); _xmlWriter.WriteString(value); _xmlWriter.WriteEndAttribute(); break; case ControlType.NodeEnd: if (holdValue != null) { _xmlWriter.WriteString(holdValue); holdValue = null; } _xmlWriter.WriteEndElement(); break; case ControlType.FileEnd: _xmlWriter.Flush(); return(_writerStream.ToArray()); } } else if (TypeDictionary.TypeMap.TryGetValue(nodeType, out propertyType)) { if (holdValue != null) { _xmlWriter.WriteString(holdValue); holdValue = null; } var elementName = _nodeBuffer.ReadString(); _xmlWriter.WriteStartElement(elementName); _xmlWriter.WriteStartAttribute("__type"); _xmlWriter.WriteString(propertyType.Name); _xmlWriter.WriteEndAttribute(); int arraySize; if (array || propertyType.Name == "str" || propertyType.Name == "bin") { arraySize = _dataBuffer.ReadS32(); //Total size. } else { arraySize = propertyType.Size * propertyType.Count; } if (propertyType.Name == "str") { holdValue = _dataBuffer.ReadString(arraySize); } else if (propertyType.Name == "bin") { _xmlWriter.WriteStartAttribute("__size"); _xmlWriter.WriteString(arraySize.ToString()); _xmlWriter.WriteEndAttribute(); holdValue = _dataBuffer.ReadBinary(arraySize); } else { if (array) { var size = (arraySize / (propertyType.Size * propertyType.Count)).ToString(); _xmlWriter.WriteStartAttribute("__count"); _xmlWriter.WriteString(size); _xmlWriter.WriteEndAttribute(); } var span = _dataBuffer.ReadBytes(arraySize); var stringBuilder = new StringBuilder(); var loopCount = arraySize / propertyType.Size; for (var i = 0; i < loopCount; i++) { var subSpan = span.Slice(i * propertyType.Size, propertyType.Size); stringBuilder.Append(propertyType.GetString(subSpan)); if (i != loopCount - 1) { stringBuilder.Append(" "); } } holdValue = stringBuilder.ToString(); } } else { throw new KbinException($"Unknown node type: {nodeType}"); } } }