我正在寻找一种简单的方法将xml转换为json,并附加选项将完整的xpath添加为属性。现在我这样做:
panic: template: :2: function "IsIPv4" not defined
但与以下相比,它看起来很迂回:
private static string XmlToJson(string xmlString)
{
return new JavaScriptSerializer().Serialize(GetXmlValues(XElement.Parse(xmlString)));
}
private static Dictionary<string, object> GetXmlValues(XElement xml)
{
var attr = xml.Attributes().ToDictionary(d => d.Name.LocalName, d => (object)d.Value);
if (xml.HasElements)
{
attr.Add("_children", xml.Elements().Select(e => GetXmlValues(e)));
attr.Add("_path", xml.GetPath());
}
else if (!xml.IsEmpty)
{
attr.Add("_value", xml.Value);
attr.Add("_path", xml.GetPath());
}
return new Dictionary<string, object> { { xml.Name.LocalName, attr } };
}
private static string GetPath(this XElement node)
{
string path = node.Name.LocalName;
XElement currentNode = node;
while (currentNode.Parent != null)
{
currentNode = currentNode.Parent;
path = currentNode.Name.LocalName + "/" + path;
}
return path;
}
但是我不知道如何在转换过程中添加路径?
答案 0 :(得分:0)
但与
相比,它看起来很迂回
Json.net使用它自己的名为JsonConverter
的XmlNodeConverter
实现。因此,如果您希望它看起来不迂回,您可以实现your own JsonConverter并使用它:
var doc = XDocument.Parse(xml);
var json = JsonConvert.SerializeObject(doc, new MyXmlWithXPathJsonConverter());
这是一项很好但非常复杂的任务。
但更简单的方法是在序列化之前将xml节点附加到xpath属性。例如:
public void AppendXPath(XContainer container)
{
if (container == null)
throw new ArgumentNullException("container");
var doc = container as XDocument;
if (doc != null)
AppendXPath(doc.Root, "", 1);
else
AppendXPath(container as XElement, "/", 1);
}
private void AppendXPath(XElement node, string parent, int num)
{
var path = $"{parent}/{node.Name}[{num}]";
if (node.Attribute("xpath") != null)
throw new InvalidOperationException($"Node {path} already contains xpath attribute");
var indicies = new Dictionary<XName, int>();
foreach (var child in node.Elements())
{
int index;
if (indicies.TryGetValue(child.Name, out index))
indicies[child.Name] = ++index;
else
indicies[child.Name] = index = 1;
AppendXPath(child, path, index);
}
node.Add(new XAttribute("xpath", path));
}
测试:
void Test()
{
var xml =
@"<xml>
<foo>
<one />
<other />
</foo>
<bar data=""abc"">
<item order=""3"" />
<item order=""1"">
<child whatever="""" />
</item>
</bar>
</xml>";
var doc = XDocument.Parse(xml);
AppendXPath(doc);
var json = JsonConvert.SerializeObject(doc, Newtonsoft.Json.Formatting.Indented);
Console.WriteLine(json);
}
结果:
{
"xml": {
"@xpath": "/xml[1]",
"foo": {
"@xpath": "/xml[1]/foo[1]",
"one": {
"@xpath": "/xml[1]/foo[1]/one[1]"
},
"other": {
"@xpath": "/xml[1]/foo[1]/other[1]"
}
},
"bar": {
"@data": "abc",
"@xpath": "/xml[1]/bar[1]",
"item": [
{
"@order": "3",
"@xpath": "/xml[1]/bar[1]/item[1]"
},
{
"@order": "1",
"@xpath": "/xml[1]/bar[1]/item[2]",
"child": {
"@whatever": "",
"@xpath": "/xml[1]/bar[1]/item[2]/child[1]"
}
}
]
}
}
}