开发者

XamlReader.Parse throws exception on empty String

In our app, we need to save properties of objects to the same database table regardless of the type of object, in the form of propertyName, propertyValue, propertyType. We decided to use XamlWriter to save all of the given object's properties. We then use XamlReader to load up the XAML that was created, and turn it back into the value for the property. This works fine for the most part, except for empty strings. The XamlWriter will save an empty string as below.

<Stri开发者_开发技巧ng xmlns="clr-namespace:System;assembly=mscorlib" xml:space="preserve" /> 

The XamlReader sees this string and tries to create a string, but can't find an empty constructor in the String object to use, so it throws a ParserException.

The only workaround that I can think of is to not actually save the property if it is an empty string. Then, as I load up the properties, I can check for which ones did not exist, which means they would have been empty strings.

Is there some workaround for this, or is there even a better way of doing this?


We had a similar problem to this when trying to serialize strings. The only way we could resolve it was to create a StringWrapper struct or class that had the appropriate constructors. We then used this type to load and save our string values.


I also got the problem and searched the web for a solution but could not find one.

I solved it by inspecting the saved XML and fixing the empty strings, like this (feed FixSavedXaml with the output from XamlWriter):

    static string FixSavedXaml(string xaml)
    {
        bool isFixed = false;
        var xmlDocument = new System.Xml.XmlDocument();
        xmlDocument.LoadXml(xaml);
        FixSavedXmlElement(xmlDocument.DocumentElement, ref isFixed);
        if (isFixed) // Only bothering with generating new xml if something was fixed
        {
            StringBuilder xmlStringBuilder = new StringBuilder();
            var settings = new System.Xml.XmlWriterSettings();
            settings.Indent = false;
            settings.OmitXmlDeclaration = true;

            using (var xmlWriter = System.Xml.XmlWriter.Create(xmlStringBuilder, settings))
            {
                xmlDocument.Save(xmlWriter);
            }

            return xmlStringBuilder.ToString();
        }

        return xaml;
    }

    static void FixSavedXmlElement(System.Xml.XmlElement xmlElement, ref bool isFixed)
    {
        // Empty strings are written as self-closed element by XamlWriter,
        // and the XamlReader can not handle this because it can not find an empty constructor and throws an exception.
        // To fix this we change it to use start and end tag instead (by setting IsEmpty to false on the XmlElement).
        if (xmlElement.LocalName == "String" &&
            xmlElement.NamespaceURI == "clr-namespace:System;assembly=mscorlib")
        {
            xmlElement.IsEmpty = false;
            isFixed = true;
        }

        foreach (var childElement in xmlElement.ChildNodes.OfType<System.Xml.XmlElement>())
        {
            FixSavedXmlElement(childElement, ref isFixed);
        }
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜