SQLParameter типа XML с элементами пробела теряет пробел?

У меня проблема с SQLParameter, когда я пытаюсь использовать его для хранения в столбце типа XML. Я создаю параметр SqlDbType.Xml. Похоже, что любые элементы XML, которые представляют собой только пробелы, преобразуются в закрытые элементы.

Это такое же поведение, как

SELECT CAST('<Cust><Fname>Andrew</Fname><Lname> </Lname></Cust>' as XML) 
VS 
SELECT CONVERT(xml, '<Cust><Fname>Andrew</Fname><Lname> </Lname></Cust>', 1)

Я удивлен, увидев это как поведение по умолчанию в SQLParameter. Есть ли способ заставить SQLParameter SqlDbType.Xml заботиться о своем пробеле? В качестве выстрела в темноте я попытался установить точность на 1, но это не помогло...

Код ниже заканчивается этим в базе данных

<Cust><Fname>Andrew</Fname><Lname /></Cust>

Как вы можете видеть, он удаляет XML-элемент пробела.

// CREATE TABLE T(c1 int primary key, c2 xml)
static void Main(string[] args) {

using (var Connection = new System.Data.SqlClient.SqlConnection("Data Source=localhost;Initial Catalog=Test;Integrated Security=SSPI;"))
{
    Connection.Open();

    using (var Command = Connection.CreateCommand())
    {
      Command.CommandText = "INSERT INTO T VALUES (1, @s)";

      var XmlParameter = Command.Parameters.Add("s", System.Data.SqlDbType.Xml);
      XmlParameter.Value = "<Cust><Fname>Andrew</Fname><Lname>  </Lname></Cust>";

      Command.ExecuteNonQuery();
    }

    Connection.Close();
}

Кто-нибудь знает способ решить эту проблему, который не анализирует параметр как двоичный и не преобразует его как часть команды вставки/обновления?

Command.CommandText = "INSERT INTO T VALUES (1, CONVERT(xml, @s, 1))";

Будем признательны за любую помощь или обратную связь.


person Tristan    schedule 20.08.2012    source источник
comment
Пробелы внутри узлов обычно игнорируются, поскольку обычно они используются только для улучшения читаемости и на самом деле не являются полезной нагрузкой документа. Вы должны иметь возможность сохранить его, см. w3.org/TR/xml11/ #sec-white-space, я не пробовал с SQL-сервером   -  person joocer    schedule 20.08.2012
comment
Вы правы, я читал об этом флаге, но не пробовал его использовать. XmlParameter.Value = ‹Cust›‹Fname›Andrew‹/Fname›‹Lname xml:space=\preserve\› ‹/Lname›‹/Cust›; Решает проблему. В моем случае использования я не всегда могу изменить входящий XML. Любые другие идеи были бы потрясающими!   -  person Tristan    schedule 20.08.2012
comment
В моем случае мы используем XML-документ в качестве заданного пользователем шаблона для форматирования исходящих сообщений /var›...‹/template› Так что мне действительно нужно сохранить пробел. Разработчик-исполнитель теперь добавил атрибут xml:space в свой сконструированный xml. Но причина, по которой я спрашиваю, заключается в том, что он проходит через очень общий DAL для хранения, где используется SQLParameter. Я думаю, что на данный момент я застрял с комбинацией INSERT / UPDATE + CONVERT. Таким образом, нашим разработчикам не нужно будет создавать правильный XML.   -  person Tristan    schedule 21.08.2012
comment
Речь идет о правилах для XML, а не о том, как с этим справляется ADO.Net/SQL. Правила XML говорят, что пробелы в этом случае не имеют значения, а также что <a></a> и <a/> полностью эквивалентны. Если это не так для того, с чем вы имеете дело, то то, с чем вы имеете дело, не является XML — это строка, очень похожая на XML.   -  person Damien_The_Unbeliever    schedule 21.08.2012


Ответы (1)


Если вы получаете XML из внешнего источника и он только начинается с элемента, вы можете добавить к строке префикс

<?xml version="1.0"?>
<!DOCTYPE Cust [
<!ATTLIST Cust xml:space (preserve) #FIXED 'preserve'>
]>

Это должно сделать так, чтобы весь документ (корневой узел Cust вниз) сохранял пробелы. Если вас интересуют только определенные поля, то вместо ATTLIST, говорящего Cust, добавьте новый ATTLIST для каждого из элементов, в которых вы хотите сохранить пробелы.

<!ATTLIST Fname xml:space (preserve) #FIXED 'preserve'>
<!ATTLIST Lname xml:space (preserve) #FIXED 'preserve'>

Опять же, я не пробовал с SQL-сервером (у меня просто нет доступа к нему), но процессор XML в IE и Chrome добавляет xml:space="preserve" в документ, как и ожидалось, что из того, что вы сказали выше дал вам поведение, которое вы искали. Этот подход делает это без глубокого манипулирования XML, вы просто добавляете некоторые директивы обработки в начало документа.

person joocer    schedule 21.08.2012