Skip to content

Commit e9dd9ec

Browse files
committed
Переопределение пространств имен при копировании атрибутов.
1 parent 8767960 commit e9dd9ec

2 files changed

Lines changed: 134 additions & 6 deletions

File tree

src/OneScript.StandardLibrary/Xml/XmlWriterImpl.cs

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ public void WriteCurrent(XmlReaderImpl reader)
196196
CopyDocumentType(reader, this);
197197
break;
198198
case XmlNodeType.Attribute:
199-
WriteAttribute(reader.Name, reader.Value);
199+
CopyAttribute(reader.Name, reader.Value, reader, this);
200200
break;
201201
case XmlNodeType.EndElement:
202202
WriteEndElement();
@@ -223,12 +223,50 @@ private static void CopyElementAndAttributes(XmlReaderImpl reader, XmlWriterImpl
223223
for (var attributeIndex = 0; attributeIndex < attributeCount; attributeIndex++)
224224
{
225225
var attributeName = reader.AttributeName(attributeIndex);
226-
var attributeValue = reader.GetAttribute(ValueFactory.Create(attributeIndex));
227-
writer.WriteAttribute(attributeName, attributeValue.ExplicitString());
226+
var attributeValue = reader.GetAttribute(ValueFactory.Create(attributeIndex)).ExplicitString();
227+
CopyAttribute(attributeName, attributeValue, reader, writer);
228228
}
229229
}
230230
}
231231

232+
private static void CopyAttribute(string attributeNameIn, string attributeValue, XmlReaderImpl reader, XmlWriterImpl writer)
233+
{
234+
var splittedName = splitName(attributeNameIn);
235+
if (!string.IsNullOrEmpty(splittedName.prefix))
236+
{
237+
var readerNsContext = (XmlNamespaceContext)reader.NamespaceContext;
238+
var writerNsContext = (XmlNamespaceContext)writer.NamespaceContext;
239+
if (splittedName.prefix.Equals("xmlns", StringComparison.Ordinal))
240+
{
241+
writer.WriteNamespaceMapping(splittedName.localName, attributeValue);
242+
return;
243+
}
244+
else
245+
{
246+
var uri = readerNsContext.LookupNamespaceUri(splittedName.prefix);
247+
if (uri is BslStringValue)
248+
{
249+
var value = uri.ExplicitString();
250+
var curentPrefix = writerNsContext.LookupPrefix(value);
251+
if (!(curentPrefix is BslStringValue && curentPrefix.ExplicitString().Equals(splittedName.prefix, StringComparison.Ordinal)))
252+
{
253+
writer.WriteNamespaceMapping(splittedName.prefix, value);
254+
}
255+
splittedName.prefix = value;
256+
}
257+
}
258+
}
259+
writer.WriteAttribute(splittedName.localName, splittedName.prefix, attributeValue);
260+
}
261+
262+
private static (string prefix, string localName) splitName(string nameOrLocalName)
263+
{
264+
var parts = nameOrLocalName.Split(':');
265+
if (parts.Length > 1) return (parts[0], parts[1]);
266+
if (parts[0].Equals("xmlns", StringComparison.Ordinal)) return (parts[0], "");
267+
return ("", parts[0]);
268+
}
269+
232270
[ContextMethod("ЗаписатьТипДокумента","WriteDocumentType")]
233271
public void WriteDocumentType(string name, string varArg2, string varArg3 = null, string varArg4 = null)
234272
{

tests/xmlwrite.os

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
ВсеТесты.Добавить("ТестДолжен_ЗаписатьТекущий_НачалоЭлемента");
3232
ВсеТесты.Добавить("ТестДолжен_ЗаписатьТекущий_НачалоВложенногоЭлемента");
3333
ВсеТесты.Добавить("ТестДолжен_ЗаписатьТекущий_АтрибутВнутриЭлемента");
34+
ВсеТесты.Добавить("ТестДолжен_ЗаписатьТекущий_АтрибутВнутриЭлементаСОпределениемПространстваИмен");
35+
ВсеТесты.Добавить("ТестДолжен_ЗаписатьТекущий_АтрибутВнутриЭлементаСПерекрывающимОпределениемПространстваИмен");
36+
ВсеТесты.Добавить("ТестДолжен_ЗаписатьТекущий_АтрибутВнутриЭлементаСЛишнимПереопределениемПространстваИмен");
3437
ВсеТесты.Добавить("ТестДолжен_ЗаписатьТекущий_КонецЭлемента");
3538
ВсеТесты.Добавить("ТестДолжен_ЗаписатьТекущий_Текст");
3639

@@ -358,6 +361,95 @@
358361

359362
КонецПроцедуры
360363

364+
Процедура ТестДолжен_ЗаписатьТекущий_АтрибутВнутриЭлементаСОпределениемПространстваИмен() Экспорт
365+
366+
Перем ЧтениеXML, ЗаписьXML;
367+
368+
ПодготовитьТестовыеДанныеДляЗаписиТекущего(ЧтениеXML, ЗаписьXML);
369+
370+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.ОбъявлениеXML, "<?xml>");
371+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.ОпределениеТипаДокумента, "<!DOCTYPE>");
372+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.НачалоЭлемента, "<xml>");
373+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.ПробельныеСимволы);
374+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.НачалоЭлемента, "<data>");
375+
ЧтениеXML.Пропустить();
376+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.ПробельныеСимволы);
377+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.НачалоЭлемента, "<ins:data>");
378+
379+
ЧтениеXML.ПервыйАтрибут();
380+
ЧтениеXML.СледующийАтрибут();
381+
382+
ЗаписьXML.ЗаписатьНачалоЭлемента("эл");
383+
ЗаписьXML.ЗаписатьТекущий(ЧтениеXML);
384+
ПолученныйТекст = ЗаписьXML.Закрыть();
385+
юТест.ПроверитьРавенство(
386+
"<эл xmlns:ins=""inner namespace mapping"" ins:attr=""1"" />", // dotnet автоматом закроет элемент
387+
ПолученныйТекст,
388+
"Автоматически добавляется определение пространства имен");
389+
390+
КонецПроцедуры
391+
392+
Процедура ТестДолжен_ЗаписатьТекущий_АтрибутВнутриЭлементаСЛишнимПереопределениемПространстваИмен() Экспорт
393+
394+
Перем ЧтениеXML, ЗаписьXML;
395+
396+
ПодготовитьТестовыеДанныеДляЗаписиТекущего(ЧтениеXML, ЗаписьXML);
397+
398+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.ОбъявлениеXML, "<?xml>");
399+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.ОпределениеТипаДокумента, "<!DOCTYPE>");
400+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.НачалоЭлемента, "<xml>");
401+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.ПробельныеСимволы);
402+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.НачалоЭлемента, "<data>");
403+
ЧтениеXML.Пропустить();
404+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.ПробельныеСимволы);
405+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.НачалоЭлемента, "<ins:data>");
406+
407+
ЧтениеXML.ПервыйАтрибут();
408+
ЧтениеXML.СледующийАтрибут();
409+
410+
ЗаписьXML.ЗаписатьНачалоЭлемента("корень");
411+
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("ins", "inner namespace mapping");
412+
ЗаписьXML.ЗаписатьНачалоЭлемента("эл");
413+
ЗаписьXML.ЗаписатьТекущий(ЧтениеXML);
414+
ПолученныйТекст = ЗаписьXML.Закрыть();
415+
юТест.ПроверитьРавенство(
416+
"<корень xmlns:ins=""inner namespace mapping""><эл ins:attr=""1"" /></корень>", // dotnet автоматом закроет элементы
417+
ПолученныйТекст,
418+
"Определение пространства имен не добавляется");
419+
420+
КонецПроцедуры
421+
422+
Процедура ТестДолжен_ЗаписатьТекущий_АтрибутВнутриЭлементаСПерекрывающимОпределениемПространстваИмен() Экспорт
423+
424+
// BSLLS:LineLength-off
425+
Перем ЧтениеXML, ЗаписьXML;
426+
427+
ПодготовитьТестовыеДанныеДляЗаписиТекущего(ЧтениеXML, ЗаписьXML);
428+
429+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.ОбъявлениеXML, "<?xml>");
430+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.ОпределениеТипаДокумента, "<!DOCTYPE>");
431+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.НачалоЭлемента, "<xml>");
432+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.ПробельныеСимволы);
433+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.НачалоЭлемента, "<data>");
434+
ЧтениеXML.Пропустить();
435+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.ПробельныеСимволы);
436+
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.НачалоЭлемента, "<ins:data>");
437+
438+
ЧтениеXML.ПервыйАтрибут();
439+
ЧтениеXML.СледующийАтрибут();
440+
441+
ЗаписьXML.ЗаписатьНачалоЭлемента("корень");
442+
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("ins2", "inner namespace mapping");
443+
ЗаписьXML.ЗаписатьНачалоЭлемента("эл");
444+
ЗаписьXML.ЗаписатьТекущий(ЧтениеXML);
445+
ПолученныйТекст = ЗаписьXML.Закрыть();
446+
юТест.ПроверитьРавенство(
447+
"<корень xmlns:ins2=""inner namespace mapping""><эл xmlns:ins=""inner namespace mapping"" ins:attr=""1"" /></корень>", // dotnet автоматом закроет элементы
448+
ПолученныйТекст,
449+
"Определение пространства имен добавляется, так как не совпадают префиксы");
450+
// BSLLS:LineLength-on
451+
КонецПроцедуры
452+
361453
Процедура ТестДолжен_ЗаписатьТекущий_КонецЭлемента() Экспорт
362454

363455
Перем ЧтениеXML, ЗаписьXML;
@@ -378,8 +470,6 @@
378470

379471
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.Текст, "Some Value");
380472
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.КонецЭлемента, "</data>");
381-
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.ПробельныеСимволы);
382-
ПрочитатьИПроверитьТип(ЧтениеXML, ТипУзлаXML.КонецЭлемента, "</xml>");
383473

384474
ЗаписьXML.ЗаписатьТекущий(ЧтениеXML);
385475

@@ -445,6 +535,7 @@
445535
|<!DOCTYPE example SYSTEM ""example.dtd"">
446536
|<xml xmlns:ns=""ns"" attr=""1"" ns:attr=""value"">
447537
| <ns:data inner=""123"" inner2=""456"" inner3=""789"">Some Text</ns:data>
538+
| <ins:data xmlns:ins=""inner namespace mapping"" ins:attr=""1""></ins:data>
448539
|</xml>"
449540
;
450541

@@ -476,4 +567,3 @@
476567
ЧтениеXML.Прочитать();
477568
юТест.ПроверитьРавенство(ЧтениеXML.ТипУзла, ТипУзла, Сообщение);
478569
КонецПроцедуры
479-

0 commit comments

Comments
 (0)