Импорт XML в объект C #

#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;
}
}
  

обновить / ответить ## (не уверен, как делать ответы ниже).

Спасибо за код и ссылку на сайт конвертера. Я добавил некоторый код и вроде бы заставил его что-то делать, но у меня есть еще несколько проблем.

  1. Как мне получить 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-файла.

  1. Я добавил в класс 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 выше все еще применяется.

  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 — Большое спасибо за расширенное объяснение, высоко ценится. Я поиграл с тем, что у вас есть, и с конвертером, и, наконец, получил что-то работающее так, как это должно быть. хотя мне действительно нужно провести дополнительные тесты для других ситуаций. Еще раз спасибо за помощь!.