好的,我实际上已经找到了解决方案,但它需要 XmlNodeConverter 的修改版本。为了保持我的影响很小,我实际上对实际代码进行了最小的更改,然后创建了一个派生类。
//added this virtual method
protected virtual string GetAttributeValue(string attributeName, JsonReader reader)
{
return reader.Value.ToString();
}
private void ReadElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, XmlNamespaceManager manager)
{
if (string.IsNullOrEmpty(propertyName))
throw new JsonSerializationException("XmlNodeConverter cannot convert JSON with an empty property name to XML.");
Dictionary<string, string> attributeNameValues = ReadAttributeElements(reader, manager);
string elementPrefix = MiscellaneousUtils.GetPrefix(propertyName);
if (propertyName.StartsWith("@"))
{
var attributeName = propertyName.Substring(1);
//Made the change below to use the new method
//var attributeValue = reader.Value.ToString();
var attributeValue = GetAttributeValue(attributeName, reader);
...
// Modified to virtual to allow derived class to override. Added attributeName parameter
protected virtual string ConvertTokenToXmlValue(string attributeName, JsonReader reader)
{
if (reader.TokenType == JsonToken.String)
{
return reader.Value.ToString();
}
....
然后我创建了以下派生的 xml 节点转换器。
public class DerivedXmlNodeConverter : Newtonsoft.Json.Converters.XmlNodeConverter
{
private Dictionary<string, string> _attributeFormatStrings;
public Dictionary<string, string> AttributeFormatStrings
{
get
{
if (_attributeFormatStrings == null)
_attributeFormatStrings = new Dictionary<string,string>();
return _attributeFormatStrings;
}
}
protected override string GetAttributeValue(string attributeName, JsonReader reader)
{
Console.WriteLine("getting attribute value: " + attributeName);
if (AttributeFormatStrings.ContainsKey(attributeName))
{
return string.Format(AttributeFormatStrings[attributeName], reader.Value);
}
else
return base.GetAttributeValue(attributeName, reader);
}
protected override string ConvertTokenToXmlValue(string attributeName, JsonReader reader)
{
if (AttributeFormatStrings.ContainsKey(attributeName))
{
return string.Format(AttributeFormatStrings[attributeName], reader.Value);
}
else
return base.ConvertTokenToXmlValue(attributeName, reader);
}
}
然后我不得不复制 JsonConvert.DeserializeXNode 所做的代码。
DerivedXmlNodeConverter derived = new DerivedXmlNodeConverter();
derived.WriteArrayAttribute = false;
derived.DeserializeRootElementName = null;
derived.AttributeFormatStrings["valDouble"] = "{0:0.000}";
JsonSerializerSettings settings = new JsonSerializerSettings { Converters = new JsonConverter[] { derived } };
StringReader sr = new StringReader(test.ToString(Newtonsoft.Json.Formatting.Indented));
JsonReader reader = new JsonTextReader(sr);
JsonSerializer ser = JsonSerializer.CreateDefault(settings);
ser.CheckAdditionalContent = true;
XDocument intoXml = (XDocument)(ser.Deserialize(reader, typeof(XDocument)));
我认为这些在 Newtownsoft 框架中会有很大的变化——允许这些钩子进行定制。我希望这段代码可以帮助其他需要它的人。
-大卫