#c# #xml
#c# #xml
Вопрос:
У меня есть XML-файл со следующим в нем:
<tooltip>
<text>My Tool Tip</text>
<color>#000000</color>
<crosshairs>
<width>3</width>
<color>green</color>
<padding>5px</padding>
</crosshairs>
<crosshairs>
<width>3</width>
<color>blue</color>
</crosshairs>
</tooltip>
Я хочу загрузить элементы «перекрестия» в объект C # — затем объект сериализуется в файл JSON:
ToolTipClass toolTip = new ToolTipClass(xmlDoc);
JavaScriptSerializer s = new JavaScriptSerializer();
string aJSON = s.Serialize(toolTip);
// aJSON is now written out to file.
У меня действительно есть класс «toolTip» с некоторыми общедоступными переменными, которые установлены по умолчанию в конструкторе. Конструктор также считывает XML-файл и перезаписывает общедоступные переменные значением из XML (например, записывается в «общедоступный текст строки;», но часть подсказки «перекрестие» может содержать либо 1, либо несколько элементов — я не хочу определять класс для перекрестия, поскольку тегов внутри перекрестия может быть больше, чем просто 2, определенных выше (ширина, цвет). например (заполнение, поля, размер шрифта и т.д.)
вывод JSon будет выглядеть примерно так:
tooltip: {
text: "My Tool Tip",
color: "#000000",
crosshairs: [{
width: 3,
color: 'green',
padding: '5px'
}, {
width: 3,
color: 'blue'
}]
}
Что мне нужно знать, так это как мне загрузить элементы crosshairs в объект, который не является предопределенным?
Я просмотрел:http://danielwylie.me/blog/2010/04/26/c-convert-xml-to-an-object-or-list-of-an-object /?Фокус = Да но при этом используется класс «person», который не является тем, что я хотел.
Большое спасибо за любую помощь / указатели.
Дополнительно: класс всплывающей подсказки:
public class ToolTip
{
public string backgroundColor = "rgba(255, 255, 255, .80)";
public string borderColor = "#764D9B";
public int borderRadius = 5;
public int borderWidth = 1;
//public string crosshairs = null;
//public List<object> crosshairs = new List<object>();
public Boolean enabled = true;
//formatter: ;
public Boolean shadow = true;
public Boolean shared = false;
public float snap = 10;
public HCCSS style = new HCCSS();
public string text = "[undefined]";
public string color = "#000000";
public HCToolTip(XmlDocument xmlDoc) {
text = findTagInXML_String(xmlDoc, "//tooltip/text", text);
color = findTagInXML_String(xmlDoc, "//tooltip/color", color);
//snip
}
static private string findTagInXML_String(XmlDocument xmlDoc, string tag, string defaultvalue) {
return xmlDoc.SelectSingleNode(tag) == null || xmlDoc.SelectSingleNode(tag).InnerText == "null" ? defaultvalue : xmlDoc.SelectSingleNode(tag).InnerText;
}
}
обновить / ответить ## (не уверен, как делать ответы ниже).
Спасибо за код и ссылку на сайт конвертера. Я добавил некоторый код и вроде бы заставил его что-то делать, но у меня есть еще несколько проблем.
-
Как мне получить XML-данные в коллекцию Crosshairs. В настоящее время у меня есть это в моем классе конструктора всплывающих подсказок:
Crosshairs c = new Crosshairs(); c.SetProperty("a",new {width="3", color="green"}); c.SetProperty("b", new { width = "3", color = "blue" }); crosshairs.Add(c);
Я предполагаю, что новый цвет ширины у меня там, где я хотел бы, чтобы он отображал детали из упомянутого выше XML-файла.
-
Я добавил в класс Converter, но результат, который я сейчас получаю, выглядит примерно так:
всплывающая подсказка: { Цвет границы: «#F00» перекрестие: { Список: [ { Значение: { ширина: «3» цвет: «зеленый»} Текст: { ширина: «3» цвет: «синий» } } ] } включено: true
}
Я изменил конвертер примеров, чтобы в нем были следующие строки:
foreach (Crosshairs item in listType) {
//Add each entry to the dictionary.
Dictionary<string, object> listDict = new Dictionary<string, object>();
listDict.Add("Value", item.GetProperty("a"));
listDict.Add("Text", item.GetProperty("b"));
itemsList.Add(listDict);
}
result["List"] = itemsList;
Как вы можете видеть, это выглядит не очень универсально, поскольку использует типы «CrosshairsCollection», но я как бы предполагаю, что я могу изменить «CrosshairsCollection» на «GenericCollection», поскольку это всего лишь словарь — так что # 1 выше все еще применяется.
- Другая проблема заключается в том, что не только всплывающая подсказка имеет этот класс «crosshairs», но у меня есть и другие классы, похожие на crosshairs — например, style, который я хотел бы иметь в той же системе.
Если бы кто-нибудь мог помочь с # 1 выше — импортировать данные из XML — в универсальный класс, а не в предопределенный класс, это действительно помогло бы.
Еще раз — Большое спасибо за помощь. Алан
Комментарии:
1. Как выглядит класс ToolTip? Можете ли вы опубликовать определение класса?
2. Спасибо, я добавил это выше. Я исправил часть с перекрестием, поскольку не смог заставить ее работать. Как вы можете видеть, в классе tooltip есть класс в стиле HCCSS, если я смогу заставить работать бит перекрестия, это было бы полезно в других классах… как в классе стилей CSS.
Ответ №1:
Определите простой тип перекрестия, который является оболочкой для строки, словаря объектов:
class CrosshairsCollection : List<Crosshairs>
{
}
class Crosshairs
{
private Dictionary<string, object> dict = new Dictionary<string,object>();
public IEnumerable<KeyValuePair<string, object>> GetAllProperties()
{
foreach (string key in dict.Keys)
{
yield return new KeyValuePair<string, object>(key, dict[key]);
}
}
public object GetProperty(string s)
{
object value;
bool exists = dict.TryGetValue(s, out value);
if (!exists)
{
value = null;
}
return value;
}
public void SetProperty(string s, object o)
{
if (!dict.ContainsKey(s))
{
dict.Add(s, o);
}
else
{
dict[s] = o;
}
}
}
Затем реализуйте JavaScriptConverter для сбора перекрестий, аналогичный этому: http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptconverter.aspx
Замените свой список на CrosshairsCollection и зарегистрируйте JavaScriptConverter в вашем экземпляре JavaScriptSerializer.
[Редактировать: ответы на последующие вопросы]
Я предполагаю, что у вас есть два последующих вопроса, оба с номером 1, и что второй — «как мне сделать вывод JSON более похожим на мой оригинальный пример?» 🙂
Способ, которым я интерпретировал ваш исходный XML, заключался в том, что всплывающая подсказка имеет несколько перекрестий, а не одно перекрестие с несколькими перекрывающимися определениями свойств. Однако представление в XML и использование вашего имени в коде не согласуются: вы называете все это «перекрестием». Имейте это в виду, когда читаете мой оригинальный и отредактированный ответ.
Итак, чтобы получить объект, который имитирует исходный XML, я ожидал бы, что вы предоставите свойства, подобные таким:
CrosshairsCollection crosshairsList = new CrosshairsCollection();
Crosshairs c1 = new Crosshairs();
c1.SetProperty("width", 3);
c1.SetProperty("color", "green");
c1.SetProperty("padding", "5px");
crosshairsList.Add(c1);
Crosshairs c2 = new Crosshairs();
c2.SetProperty("width", 3);
c2.SetProperty("color", "blue");
crosshairsList.Add(c2);
Сделайте еще один шаг вперед, превратите каждую инициализацию перекрестия в фабричный метод и подключите его к вашему XML-представлению, как вы делаете в HCToolTip
конструкторе.
Затем вы можете добавить каждую пару имя-значение в выходные данные JSON в том виде, в каком они есть:
foreach (Crosshairs crosshairs in crosshairsList) {
Dictionary<string, object> crosshairProps = new Dictionary<string, object>();
foreach (KeyValuePair<string, object> prop in crosshairs.GetAllProperties()) {
crosshairProps.Add(prop.Key, prop.Value);
}
itemsList.Add(crosshairProps);
}
result["crosshairs"] = itemsList;
Возможно, вам потребуется реализовать JavaScriptConverter на один уровень выше, во всплывающей подсказке, чтобы получить анонимный список в качестве значения свойства для ToolTip.crosshairs
.
Я надеюсь, что это показывает, что на самом деле все, что вы ищете, — это коллекция ключей / значений. Я назвал классы CrosshairsCollection
и Crosshairs
, чтобы попытаться провести различие между списком <crosshairs>
тегов и поддеревом <crosshairs>
тега. Но вы могли бы назвать их MultiPropertyItemCollection
и MultiPropertyItem
или как угодно, потому что в реализации нет ничего специфичного для типа.
Комментарии:
1. Спасибо за ответ. Я попробую это завтра, когда вернусь в офис.
2. Не уверен, как я могу дать полный ответ на это — новое в stackoverflow.. Вместо этого отредактирую мой приведенный выше вопрос.
3. mcw0933 — Большое спасибо за расширенное объяснение, высоко ценится. Я поиграл с тем, что у вас есть, и с конвертером, и, наконец, получил что-то работающее так, как это должно быть. хотя мне действительно нужно провести дополнительные тесты для других ситуаций. Еще раз спасибо за помощь!.