Что является неправильным в отношении моего свойства XML / C # boolean? [Дубликат]

Теперь возможно, что версия 25.3.0 для вызова setSelectedItemId() \ o /

13
задан franzlorenzon 23 April 2013 в 09:40
поделиться

9 ответов

Вы можете прочитать это значение как строку в поле строки, а затем иметь поле readoolly bool, в котором в нем есть оператор if, чтобы вернуть bool true или false.

Например (с использованием c #):

public bool str2bool(string str)
{
  if (str.Trim().ToUpper() == "TRUE")
      return true;
  else
      return false;
}

И вы можете использовать его в шаблоне:

<xsl:if test="user:str2bool($mystr)">
5
ответ дан Marcin 23 August 2018 в 02:23
поделиться
  • 1
    Вы должны включить пример этого. Вероятно, у вас есть лучшее предложение, если вы это сделаете. – John Saunders 20 July 2009 в 20:21

Не беспокойтесь, исправляя сломанную систему xml или сражаясь с XmlSerializer, особенно для чего-то такого тривиального. Это не стоит. VB6 не вернется в ближайшее время.

Вместо этого возьмите документ перед его десериализацией и измените значения. Если вы беспокоитесь об изменении их за пределами тегов, используйте регулярные выражения или включите угловые скобки в значениях.

    xml = xml.Replace("True", "true").Replace("False", "false");

Он не выиграет никаких наград за элегантность, но он вернет вас работать. Иногда вам нужно иметь синий воротник.

Что касается производительности, да, вы повторяете строку O (n), но поскольку строки замены имеют одинаковую длину, это не требует каких-либо перемещений Строковые элементы вокруг. Кроме того, в зависимости от реализации может возникнуть больший накладные расходы при модификации XmlSerializer.

-1
ответ дан ATL_DEV 23 August 2018 в 02:23
поделиться
  • 1
    Вы предполагаете, что у вас есть легкий доступ к исходному HTML, чтобы иметь возможность выполнять поиск и замену, поэтому ваш ответ не является хорошим. Не говоря уже о том, большой ли пакет XML, ваш код будет генерировать огромную временную строку дважды, потому что строки в .net неизменяемы. – Kendall Bennett 2 December 2017 в 05:01
  • 2
    @KendallBennett Хорошо, вы тоже не предполагаете, что у него есть доступ к классам? Я никогда не видел случая, когда вы можете десериализовать данные, не имея доступа к входу xml. Если вы действительно обеспокоены производительностью и памятью, вам действительно следует избегать использования XmlSerializer, поскольку использует отражение, которое является одной из самых дорогих операций в .NET. В моем решении ничего не говорится о том, что он не может работать с потоковыми данными. Я хочу сказать, что наивные реализации иногда являются лучшими. Я узнал об этом. – ATL_DEV 2 December 2017 в 06:04
  • 3
    Вы не можете просто заблокировать замену всего в XML, который является True с true и False с false. Это, безусловно, наивно и, конечно, собирается сломать некоторые ответы. Что, если в нем было что-то, что было чувствительным к регистру, и в нем было слово True? Вдруг это уже не работает ... – Kendall Bennett 3 December 2017 в 09:04
  • 4
    Да, поэтому я упомянул о поиске шаблона типа & quot; & gt; False & lt; & quot; если это вызывает беспокойство. Опять же, моя реализация уродлива, но обрабатывает несовместимости. Как правило, это называется нормализацией и является стандартной практикой при рассмотрении несовместимостей и несоответствий. Он должен быть отделен от стандартной реализации. В идеале, это должно быть сделано вне программы в качестве препроцесса. Ваша реализация будет идеальной, если «True» и "False" были стандартными, но XmlSerilizer не поддерживал его. – ATL_DEV 3 December 2017 в 14:49

На основе другого вопроса о переполнении стека вы можете выполнить:

public class MySerilizedObject
{
    [XmlIgnore]
    public bool BadBoolField { get; set; }

    [XmlElement("BadBoolField")]
    public string BadBoolFieldSerialize
    {
        get { return this.BadBoolField ? "True" : "False"; }
        set
        {
            if(value.Equals("True"))
                this.BadBoolField = true;
            else if(value.Equals("False"))
                this.BadBoolField = false;
            else
                this.BadBoolField = XmlConvert.ToBoolean(value);
        }
    }
}
4
ответ дан Community 23 August 2018 в 02:23
поделиться

Нет. Сериализатор XML работает с XML-схемой, а «True» и «False» недействительны. Booleans.

Вы можете использовать XML Transform для преобразования этих двух значений или реализовать интерфейс IXmlSerializable и выполнить сериализации и десериализации.

3
ответ дан John Saunders 23 August 2018 в 02:23
поделиться
  • 1
    вы правы, Джон, вот что происходит, когда вы отвечаете перед обедом: \ .. но, честно говоря, ваше предложение Xml Transform потенциально может также преобразовать значение, которое не предназначено для булевых. – Stan R. 20 July 2009 в 21:03
  • 2
    Вообще-то, нет. Я хотел бы, чтобы он явно ссылался только на атрибуты и / или на элементы, которые являются логическими. Я не хотел преобразовывать каждый атрибут. – John Saunders 20 July 2009 в 21:08
  • 3
    Понял Джон. – Stan R. 20 July 2009 в 21:15

Вот гораздо более чистое решение, которое я придумал, основываясь на некоторых других вопросах, которые я нашел. Это намного чище, потому что тогда вам не нужно ничего в коде, кроме объявления типа SafeBool, например:

public class MyXMLClass
{
    public SafeBool Bool { get; set; }
    public SafeBool? OptionalBool { get; set; }
}

вы даже можете сделать их необязательными, и все это просто работает. Эта структура SafeBool будет обрабатывать любые варианты вариантов true / false, yes / no или y / n. Он всегда будет сериализован как true / false, однако у меня есть другие структуры, подобные этому, которые я использую для сериализации в качестве y / n или yes / no, когда это требует схема (то есть: BoolYN, BoolYesNo structs).

using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace AMain.CommonScaffold
{
    public struct SafeBool : IXmlSerializable
    {
        private bool _value;

        /// <summary>
        /// Allow implicit cast to a real bool
        /// </summary>
        /// <param name="yn">Value to cast to bool</param>
        public static implicit operator bool(
            SafeBool yn)
        {
            return yn._value;
        }

        /// <summary>
        /// Allow implicit cast from a real bool
        /// </summary>
        /// <param name="b">Value to cash to y/n</param>
        public static implicit operator SafeBool(
            bool b)
        {
            return new SafeBool { _value = b };
        }

        /// <summary>
        /// This is not used
        /// </summary>
        public XmlSchema GetSchema()
        {
            return null;
        }

        /// <summary>
        /// Reads a value from XML
        /// </summary>
        /// <param name="reader">XML reader to read</param>
        public void ReadXml(
            XmlReader reader)
        {
            var s = reader.ReadElementContentAsString().ToLowerInvariant();
            _value = s == "true" || s == "yes" || s == "y";
        }

        /// <summary>
        /// Writes the value to XML
        /// </summary>
        /// <param name="writer">XML writer to write to</param>
        public void WriteXml(
            XmlWriter writer)
        {
            writer.WriteString(_value ? "true" : "false");
        }
    }
}
0
ответ дан Kendall Bennett 23 August 2018 в 02:23
поделиться
  • 1
    Посмотрите мой поиск и замените ответ. У вас много кода, который может быть лучше O (n), но иногда проблема просто требует решения Росса Перо. откройте капот и исправьте его. – ATL_DEV 1 December 2017 в 03:14

В специальном случае есть невероятно простое и короткое решение.

Сегодня я столкнулся с аналогичной проблемой, с внешним XML-файлом, который содержит значения TRUE / FALSE, которые должны иметь логическое значение значение.

Если для приложения не обязательно, чтобы десериализованный документ содержал собственный bool, но он просто требует десериализации его для чего-то, что ограничено любыми двумя альтернативными значениями, тогда можно просто использовать перечисление (здесь для атрибута в качестве примера):

public enum BOOL {FALSE, TRUE};

public MyClass
{
    [XmlAttribute]
    public BOOL MyStrangeBooleanAttribute {get; set;}
}

Это будет просто десериализовать без каких-либо проблем из элемента вроде этого

<MyClass MyStrangeBooleanAttribute = "TRUE" />

Конечно, это невозможно использовать свойство в коде для прямых логических операций, например

if (MyStrangeBooleanAttribute) // ... doesn't work

Я думаю, что, возможно, с этим можно было бы справиться, указав неявное преобразование, но я его не тестировал, потому что я не это нужно.

0
ответ дан oliver 23 August 2018 в 02:23
поделиться

Вместо использования True или False используйте 0 или 1. Он будет работать для Boolean.

5
ответ дан Raja Chandrasekaran 23 August 2018 в 02:23
поделиться

Я не думаю, что есть. Вы можете сделать это строкой и выполнить сравнение (String.Compare) , установив для параметра ignoreCase значение true.

1
ответ дан SwDevMan81 23 August 2018 в 02:23
поделиться

Я наткнулся на ту же проблему и, основываясь на ответе jman, я решил это так:

    [XmlIgnore]
    public bool BadBoolField { get; set; }

    [XmlAttribute("badBoolField")]
    public string BadBoolFieldSerializable
    {
        get
        {
            return this.BadBoolField.ToString();
        }
        set
        {
            this.BadBoolField= Convert.ToBoolean(value);
        }
    }

Помните, что это не обязательно по спецификации XML / Serialization, но она работает хорошо и он может обрабатывать широко распространенные значения преобразования (например, строки типа «True», «true», если вы замените ограничение на строку, в которой она также могла бы обрабатывать числа).

0
ответ дан this.myself 23 August 2018 в 02:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: