1 #ifndef DYNAMIC_DEPTH_INTERNAL_XMPMETA_XML_SERIALIZER_IMPL_H_ // NOLINT 2 #define DYNAMIC_DEPTH_INTERNAL_XMPMETA_XML_SERIALIZER_IMPL_H_ // NOLINT 3 4 #include <libxml/tree.h> 5 6 #include <string> 7 #include <unordered_map> 8 9 #include "xmpmeta/xml/serializer.h" 10 11 namespace dynamic_depth { 12 namespace xmpmeta { 13 namespace xml { 14 15 // Writes properties, lists, and child nodes into an XML structure. 16 // 17 // Usage example: 18 // std::unordered_map<string, xmlNsPtr> namespaces; 19 // string device_name("Device"); 20 // string cameras_name("Cameras"); 21 // string camera_name("Camera"); 22 // string audio_name("Audio"); 23 // string image_name("Image"); 24 // PopulateNamespaces(&namespaces); 25 // DoSerialization(); 26 // 27 // // Serialization example. 28 // void DoSerialization() { 29 // xmlNodePtr device_node = xmlNewNode(nullptr, device_name); 30 // Serializer device_serializer(namespaces, device_node); 31 // 32 // std::unique_ptr<Serializer> cameras_serializer = 33 // serializer->CreateListSerializer(cameras_name); 34 // for (XdmCamera *camera : camera_list_) { 35 // std::unique_ptr<Serializer> camera_serializer = 36 // cameras_serializer->CreateItemSerializer("Device", camera_name); 37 // success &= camera->Serialize(camera_serializer.get()); 38 // 39 // // Serialize Audio. 40 // std::unique_ptr<Serializer> audio_serializer = 41 // camera_serializer->CreateSerializer("Camera", audio_name); 42 // audio_serializer->WriteProperty(camera_name, "Data", audio_data); 43 // audio_serializer->WriteProperty(camera_name, "Mime", "audio/mp4"); 44 // 45 // // Serialize Image. 46 // std::unique_ptr<Serializer> image_serializer = 47 // camera_serializer->CreateSerializer("Camera", image_name); 48 // image_serializer->WriteProperty(image_name, "Data", image_data); 49 // image_serializer->WriteProperty(image_name, "Mime", "image/jpeg"); 50 // 51 // // Serialize ImagingModel. 52 // std::unique_ptr<Serializer> imaging_model_serializer = 53 // camera_serializer->CreateSerializer("Camera", "ImagingModel"); 54 // std::unique_ptr<Serializer> equirect_model_serializer = 55 // imaging_model_serializer->CreateSerializer("Camera", 56 // "EquirectModel"); 57 // // Serializer equirect model fields here. 58 // } 59 // } 60 // 61 // Resulting XML structure: 62 // /* 63 // * <Device> 64 // * <Device:Cameras> 65 // * <rdf:Seq> 66 // * <rdf:li> 67 // * <Device:Camera> 68 // * <Camera:Audio Audio:Mime="audio/mp4" Audio:Data="DataValue"/> 69 // * <Camera:Image Image:Mime="image/jpeg" Image:Data="DataValue"/> 70 // * <Camera:ImagingModel> 71 // * <Camera:EquirectModel ...properties/> 72 // * </Camera:ImagingModel> 73 // * </Device:Camera> 74 // * </rdf:li> 75 // * </rdf:Seq> 76 // * </Device:Cameras> 77 // * </Device> 78 // */ 79 // 80 // // Namespace population example. 81 // void PopulateNamespaces(std::unordered_map<string, xmlNsPtr>* namespaces) { 82 // xmlNsPtr device_ns = 83 // xmlNewNs(nullptr, ToXmlChar("http://ns.xdm.org/photos/1.0/device") 84 // ToXmlChar(device_name.data())); 85 // xmlNsPtr camera_ns = 86 // xmlNewNs(nullptr, ToXmlChar("http://ns.xdm.org/photos/1.0/camera") 87 // ToXmlChar(camera_name.data())); 88 // xmlNsPtr audio_ns = 89 // xmlNewNs(nullptr, ToXmlChar("http://ns.xdm.org/photos/1.0/audio") 90 // ToXmlChar(audio_name.data())); 91 // xmlNsPtr image_ns = 92 // xmlNewNs(nullptr, ToXmlChar("http://ns.xdm.org/photos/1.0/image") 93 // ToXmlChar(image_name.data())); 94 // namespaces->insert(device_name, device_ns); 95 // namespaces->insert(camera_name, camera_ns); 96 // namespaces->insert(audio_name, audio_ns); 97 // namespaces->insert(image_name, image_ns); 98 // } 99 100 class SerializerImpl : public Serializer { 101 public: 102 // Constructor. 103 // The prefix map is required if one of the CreateSerializer methods will be 104 // called on this object. In particular, the RDF namespace must be present in 105 // the prefix map if CreateItemSerializer or CreateListSerializer will be 106 // called. 107 // The namespaces map serves to keep XML namespace creation out of this 108 // Serializer, to simplify memory management issues. Note that the libxml 109 // xmlDocPtr will own all namespace and node pointers. 110 // The namespaces parameter is a map of node names to full namespaces. 111 // This contains all the namespaces (nodes and properties) that will be used 112 // in serialization. 113 // The node parameter is the caller node. This will be the node in which 114 // serialization takes place in WriteProperties. 115 SerializerImpl(const std::unordered_map<string, xmlNsPtr>& namespaces, 116 xmlNodePtr node); 117 118 // Returns a new Serializer for an object that is part of an rdf:Seq list 119 // of objects. 120 // The parent serializer must be created with CreateListSerializer. 121 std::unique_ptr<Serializer> CreateItemSerializer( 122 const string& prefix, const string& item_name) const override; 123 124 // Returns a new Serializer for a list of objects that correspond to an 125 // rdf:Seq XML node, where each object is to be serialized as a child node of 126 // every rdf:li node in the list. 127 // The serializer is created on an rdf:Seq node, which is the child of a 128 // newly created XML node with the name list_name. 129 std::unique_ptr<Serializer> CreateListSerializer( 130 const string& prefix, const string& list_name) const override; 131 132 // Creates a serializer from the current serializer. 133 // @param node_name The name of the caller node. This will be the parent of 134 // any new nodes or properties set by this serializer. 135 std::unique_ptr<Serializer> CreateSerializer( 136 const string& node_ns_name, const string& node_name) const override; 137 138 // Writes the property into the current node, prefixed with prefix if it 139 // has a corresponding namespace href in namespaces_, fails otherwise. 140 // Returns true if serialization is successful. 141 // If prefix is empty, the property will not be set on an XML namespace. 142 // name must not be empty. 143 // value may be empty. 144 bool WriteBoolProperty(const string& prefix, const string& name, 145 bool value) const override; 146 bool WriteProperty(const string& prefix, const string& name, 147 const string& value) const override; 148 149 // Writes the collection of numbers into a child rdf:Seq node. 150 bool WriteIntArray(const string& prefix, const string& array_name, 151 const std::vector<int>& values) const override; 152 bool WriteDoubleArray(const string& prefix, const string& array_name, 153 const std::vector<double>& values) const override; 154 155 // Class-specific methods. 156 // Constructs a serializer object and writes the xmlNsPtr objects in 157 // namespaces_ to node_. 158 static std::unique_ptr<SerializerImpl> FromDataAndSerializeNamespaces( 159 const std::unordered_map<string, xmlNsPtr>& namespaces, xmlNodePtr node); 160 161 // Disallow copying. 162 SerializerImpl(const SerializerImpl&) = delete; 163 void operator=(const SerializerImpl&) = delete; 164 165 private: 166 // Writes the xmlNsPtr objects in namespaces_ to node_. 167 // Modifies namespaces_ by setting each xmlNsPtr's next pointer to the 168 // subsequent entry in the collection. 169 bool SerializeNamespaces(); 170 171 xmlNodePtr node_; 172 std::unordered_map<string, xmlNsPtr> namespaces_; 173 }; 174 175 } // namespace xml 176 } // namespace xmpmeta 177 } // namespace dynamic_depth 178 179 #endif // DYNAMIC_DEPTH_INTERNAL_XMPMETA_XML_SERIALIZER_IMPL_H_ // NOLINT 180