2

I have got a requirement where business people would be uploading the xml files (not more than 25 file) as multimedia components and we need to expose them as JSON. I started on the POC and after a bit of trial and error I am able to achieve it as below.

Is this approach achievable in Prod environment? As i am doubtful that It might cause an issue (memory leaks, etc) in an environment where the WCM is used heavily and performance is the highest priority. I am getting this thought seeing memory stream and xml files of sizes around 2MB.

I am confused in deciding the approach even though the below is working because I am fairly new to these kind of stream objects.

 public void Transform(Engine engine, Package package)
    {

    try
    {
        Initialize(engine, package);

        Item componentItem = Package.GetByType(ContentType.Component);
        Component component = engine.GetObject(componentItem) as Component;
        XmlDocument doc = new XmlDocument();

            using (MemoryStream memoryStream = new MemoryStream())
            {
                BinaryContent binary = component.BinaryContent;
                binary.WriteToStream(memoryStream);                  
                xmlDoc.Load(memoryStream);
                memoryStream.Close();
            }

            string jsonoutput = new JavaScriptSerializer().Serialize(GetXmlValues(XElement.Parse(doc.OuterXml)));

            package.PushItem(Package.OutputName, Package.CreateStringItem(ContentType.Text, jsonoutput));


    }
    catch (Exception ex)
    {
        Logger.Error("Exception raised:" + ex.Message);
    }
}

private Dictionary<string, object> GetXmlValues(XElement xml)
{
    var attr = xml.Attributes().ToDictionary(d => d.Name.LocalName, d => (object)d.Value);
    if (xml.HasElements) attr.Add("_value", xml.Elements().Select(e => GetXmlValues(e)));
    else if (!xml.IsEmpty) attr.Add("_value", xml.Value);

    return new Dictionary<string, object> { { xml.Name.LocalName, attr } };
}
  • Can you elaborate on why you want to store XML data as a Multimedia Component instead of as a "regular" Component? – Rick Pannekoek Apr 25 '17 at 17:12
  • We dont want the business users to mess up the xml while copy pasting into a regular component. – Guest19876 Apr 26 '17 at 10:32
  • You could use WebDAV to let the Business Users upload complete XML files into regular XML components ... – Rick Pannekoek Apr 26 '17 at 17:54
3

If what you need is JSON, rather than processing this at publish time, might it not be easier (and better for performance) to process it at creation time already?

For starters I would never suggest to use a Multimedia Component for this, since it is not a binary, but a text file you are dealing with. If you wanted to store the XML, you should simply create a Schema for it and store it as a regular Component. However since what you need is JSON, I would suggest to create an event handler which on creation of the Component transforms the XML into JSON and stores it in a text field of the Component.

As mentioned my Rick already, to convert the XML into JSON, you can best use Json.NET, see also https://stackoverflow.com/questions/814001/how-to-convert-json-to-xml-or-xml-to-json#814027

  • This would be a pain as while copying the xml, business users might mess up the xml and hence this approach isn't accepted. But personally, I like this approach. – Guest19876 Apr 26 '17 at 10:30
  • If the content must remain valid XML, definitely don't choose for Multimedia Components and create a Schema for it and store it as a normal Component. – Bart Koopman Apr 26 '17 at 10:32
3

Apart from the question why you would want to store XML data in a BLOB instead of in a regular/structured/XML Component, I have the following comments on your code:

  • You are first loading the binary data into an in-memory buffer (MemoryStream), then parse it into an XML DOM (XmlDocument), then serialize it to an XML string (doc.OuterXml), then parse it into another kind of XML DOM (XElement.Parse) and finally transform it into a Dictionary which is serialized to a JSON string. Obviously, this is not very efficient; you only need one kind of XML DOM -- get rid of the LINQ to XML and query the XmlDocument directly or get the XML string directly from the MemoryStream using a StreamReader.
  • JavaScriptSerializer is one of the least efficient JSON serializers. JSON.NET is one of the most efficient ones (but a third party component, which you would have to ILMerge in your .NET Assembly TBB). DataContractJsonSerializer is inbetween, but conveniently part of the .NET Framework. See: http://www.newtonsoft.com/json/help/html/JsonNetVsDotNetSerializers.htm
  • Json.net seems to be a good option and thanks for pointing out the performance pitfalls. – Guest19876 Apr 26 '17 at 10:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.