JSON。. NET框架可以将XML转换为JSON,但它使用JSON中的@符号作为属性。我宁愿在将它发送给视图之前删除它。最好的方法是什么?
我知道我可以做一个直接的替换,但@字符可能是相关的地方,不应该被替换。这有正则表达式吗?
public ActionResult Layout()
{
var xml = new XmlDocument();
xml.XmlResolver = null;
xml.Load(Server.MapPath("~/App_Data/Navigation.xml"));
return Content(JsonConvert.SerializeXmlNode(xml, Newtonsoft.Json.Formatting.Indented));
}
{
"Layout": {
"Navigation": [
{
"@Type": "Menu",
"@Title": "Dashboard"
},
{
"@Type": "Menu",
"@Route": "Events",
"@Title": "Events",
"Navigation": {
"@Type": "Action",
"@Route": "Event",
"@Title": "+ Add Event",
"@Order": "1",
"Navigation": {
"@Type": "Item",
"@Route": "Event",
"@Name": "Event",
"Navigation": [
{
"@Route": "Pools",
"@Type": "SubNavigation",
"@Name": "Pools"
},
{
"@Route": "Brackets",
"@Type": "SubNavigation",
"@Name": "Brackets"
}
]
}
}
}
]
}
}
我花了很长时间才找到正确的答案,所以我想和大家分享一下:
var xDocument = XDocument.Parse("<xml><a attr="b">c</a></xml>");
var builder = new StringBuilder();
JsonSerializer.Create().Serialize(new CustomJsonWriter(new StringWriter(builder)), xDocument);
var serialized = builder.ToString();
public class CustomJsonWriter : JsonTextWriter
{
public CustomJsonWriter(TextWriter writer): base(writer){}
public override void WritePropertyName(string name)
{
if (name.StartsWith("@") || name.StartsWith("#"))
{
base.WritePropertyName(name.Substring(1));
}
else
{
base.WritePropertyName(name);
}
}
}
输出:{"xml":{"a":{"attr":"b","text":"c"}}}
我使用了这个。如果有更好的方法,请告诉我。
public ActionResult Layout()
{
var xml = new XmlDocument();
xml.XmlResolver = null;
xml.Load(Server.MapPath("~/App_Data/Navigation.xml"));
var jsonText = JsonConvert.SerializeXmlNode(xml, Newtonsoft.Json.Formatting.Indented);
return Content(Regex.Replace(jsonText, "(?<=")(@)(?!.*":\s )", string.Empty, RegexOptions.IgnoreCase));
}
Regex并不总是工作得很好,当内容有@字符时,首先,它也会被替换。所以我认为(?<!:)("@)(?!.":\s )
可能更好。
另一个选择是从JsonConverter
继承创建自己的OneWayXmlNodeConverter
,并调用SerializeObject
而不是SerializeXmlNode
,像这样:
var json = JsonConvert.SerializeObject(xmlNode, new OneWayXmlNodeConverter());
我称之为"单向",因为我假设默认的XmlNodeConverter
添加了"@"符号,因此它可以从结果JSON转换回XML。
如果您在项目中包含JSON.NET
源代码(而不仅仅是编译库),创建OneWayXmlNodeConverter
的简单方法是复制XmlNodeConverter
代码,在私有GetPropertyName
方法中删除硬编码的"@"符号,并将其保存为OneWayXmlNodeConverter
。
注意:我知道你的问题是特定于"替换"@"符号,但是这个问题的链接的预防变化被标记为重复。
已经有一段时间没有回复了,但这可能仍然对某人有所帮助。因为已经有了XMLDocument,所以可以在序列化它之前删除和转换属性。我尝试删除属性或将它们转换为元素。
public static void RemoveAllAttributes(XmlDocument xmlDocument)
{
if (xmlDocument == null || !xmlDocument.HasChildNodes) return;
foreach (var xmlElement in xmlDocument.SelectNodes(".//*").Cast<XmlElement>().Where(xmlElement => xmlElement.HasAttributes))
{
xmlElement.Attributes.RemoveAll();
}
}
public static void ElementifyAllAttributes(XmlDocument xmlDocument)
{
if (xmlDocument == null || !xmlDocument.HasChildNodes) return;
foreach (var xmlElement in xmlDocument.SelectNodes(".//*").Cast<XmlElement>().Where(xmlElement => xmlElement.HasAttributes))
{
foreach (XmlAttribute xmlAttribute in xmlElement.Attributes)
{
xmlElement.AppendChild(xmlDocument.CreateElement(xmlAttribute.Name)).InnerText = xmlAttribute.Value;
}
xmlElement.Attributes.RemoveAll();
}
}
然后;
private static string XmlToJson(XmlDocument xmlDocument)
{
if (xmlDocument == null) return null;
//Remove xml declaration
xmlDocument.RemoveChild(xmlDocument.FirstChild);
//Convert attributes to elements
ElementifyAllAttributes(xmlDocument);
return JsonConvert.SerializeXmlNode(xmlDocument, Formatting.None, false);
}
如果由于'@'符号而想要访问属性的值,请执行以下操作:
Navigation["@Type"]
这是我的regex贡献,使用前向和后向来确保它只发生在属性字段
(?m)(?<=^s+")(@)(?=.+":)
(?m)
-以多行模式运行
(?<=^s+")
-向后查找行开头,一个或多个空格和引号
(@)
-匹配引号后面的@
(?=.+":)
-向前查找匹配任何字符至少一次,后面跟着另一个引号,然后是冒号
我建议使用以下regex,它与@ yiieio提供的相同,但增强使内容保持原样而不做任何修改,并且只影响属性名称
var jString = Regex.Replace(
JsonConvert.SerializeXmlNode(content, Newtonsoft.Json.Formatting.None, true),
"(?<=(\,\"|\{\"))(@)(?!.*\":\\s )", String.Empty, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
如果JSON是缩进的,这可以工作:
Regex.Replace(result, @"(s*)""@(.*)"":", @"$1""$2"":", RegexOptions.IgnoreCase);
首先用一些占位符替换xml内容中的所有"@"(例如{{at_the_rate}})。然后使用下面的代码
JsonConvert.SerializeXmlNode(doc).Replace("@", "").Replace("{{at_the_rate}}", "@")