2009-09-29 3 views
12

У нас есть поле строки, которое может содержать XML или обычный текст. XML не содержит заголовка <?xml, и ни один корневой элемент, т. Е. Не сформирован.Как определить, является ли строка xml?

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

В настоящее время я использую этот подход:

string redact(string eventDetail) 
{ 
    string detail = eventDetail.Trim(); 
    if (!detail.StartsWith("<") && !detail.EndsWith(">")) return eventDetail; 
    ... 

Есть ли лучший способ?

Есть ли какие-либо краевые случаи, которые этот подход мог бы пропустить?

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

Вот пример данных XML, помимо отсутствует корневой элемент (который опущен для экономии места, так как там будет много данных), мы можем предположить, что это хорошо образован:

<TableName FirstField="Foo" SecondField="Bar" /> 
<TableName FirstField="Foo" SecondField="Bar" /> 
... 

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

РЕШЕНИЕ

на основе нескольких замечаний (спасибо, ребята!)

string redact(string eventDetail) 
{ 
    if (string.IsNullOrEmpty(eventDetail)) return eventDetail; //+1 for unit tests :) 
    string detail = eventDetail.Trim(); 
    if (!detail.StartsWith("<") && !detail.EndsWith(">")) return eventDetail; 
    XmlDocument xml = new XmlDocument(); 
    try 
    { 
     xml.LoadXml(string.Format("<Root>{0}</Root>", detail)); 
    } 
    catch (XmlException e) 
    { 
     log.WarnFormat("Data NOT redacted. Caught {0} loading eventDetail {1}", e.Message, eventDetail); 
     return eventDetail; 
    } 
    ... // redact 
+0

Я бы пошел с LoadXml, так что вы знаете, что введенные данные «XML» действительны. Если вы используете свой метод (код), у вас может быть неверный XML, который пройдет тест. – Martin

+0

См. Http://stackoverflow.com/questions/1072158/validate-xml-syntax-only-in-c – Graviton

+0

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

ответ

3

Одной из возможностей является объединение обоих решений. Вы можете использовать свой метод redact и попытаться загрузить его (внутри if). Таким образом, вы только попытаетесь загрузить то, что может быть хорошо сформированным xml, и отбросить большинство записей, отличных от xml.

+0

Хорошо, спасибо. – si618

+0

Я отметил это как наиболее подходящий ответ, потому что я думаю, что он решает мою проблему наиболее эффективным способом В большинстве случаев StartsWith <и EndsWith> будет отфильтровывать данные, отличные от xml, и для редких ситуаций, подобных описанию Иры Бакстер, ловушка XmlException решит их. – si618

8

Если вы собираетесь принимать не хорошо сформирован XML, в первую очередь, я думаю, что отлов исключения является лучший способ справиться с этим.

+0

Я бил вас на 2 секунды, Ха! – Martin

+0

Ха, ха! Ты победил! – lod3n

+0

Вы также можете отредактировать сообщение и поставить «Первым!». – Spence

2

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

+0

Я не думаю, что «XmlDocument» - хороший выбор здесь - ему не нужен DOM, просто для проверки. Похож на 'XmlReader' и' try {while (reader.Read();} catch (XmlException ex) {...} 'будет более легким. –

+0

@Pavel, но мне также нужно изменить Xml для редактирования данные, следовательно, необходимость в XmlDocument. – si618

+0

Согласен, но если я объединю подходы (по идее Самуэля), то я должен поймать 99% обычного текста с помощью кода StartsWith и EndsWith и оставить остальных 1% если LoadXml выбрасывает XmlException. – si618

0

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

foo<bar/>baz 

Фактически любая текстовая строка будет действительным фрагментом XML (рассмотрим, был ли исходный XML-документ только корневым элементом, обертывающим некоторый текст, и вы удаляете теги корневого элемента)!

1

Зависит от того, насколько точным является ваш тест. Учитывая, что у вас уже нет официального < xml, вы уже пытаетесь обнаружить что-то, что не является XML. В идеале вы должны анализировать текст с помощью полного XML-парсера (как вы предлагаете LoadXML); все, что он отвергает, - это не XML. Вопрос в том, что вас беспокоит, если вы принимаете строку, отличную от XML? Например, ты в порядке с принятием

<the quick brown fox jumped over the lazy dog's back> 

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

+0

Да, это то, чего я боюсь попасть. – si618

1

Как поступают данные? Каков другой тип данных, окружающих его? Возможно, есть лучший способ; возможно, вы можете подделать данные, которыми вы управляете, а затем сделать вывод, что все, что не входит в эти токены, это XML, но нам нужно знать больше.

Неудачное решение такого рода, я думаю, что у вас все хорошо (для проверки того, что он начинается и заканчивается этими символами).

Нам нужно знать больше о формате данных.

0
try 
{ 
    XmlDocument myDoc = new XmlDocument(); 
    myDoc.LoadXml(myString); 
} 
catch(XmlException ex) 
{ 
    //take care of the exception 
} 
+1

Конечно, и это указано в вопросе. Но перехватывание исключений дорого, когда я знаю, что многие данные не являются xml. – si618

Смежные вопросы