Я получаю сообщения Swift MX, и мне нужно удалить из них пространства имен. По сути, это два XML-документа, склеенных вместе. Чаще всего они выглядят так:
<AppHdr> содержимое заголовка </AppHdr><Document> содержимое документа </Document>
С этим легко справиться, поскольку я поставил <root> и </root> вокруг всего этого, чтобы создать XML (только один корневой узел) и прочитать его в XmlDocument:
<root><AppHdr> ... </AppHdr><Document> ... </Document></root>
Однако некоторые сообщения имеют пространства имен, и это пространство имен неизвестно во время разработки. Примером может быть:
<ns2:AppHdr xmlns:ns2 = "some stuff"> содержимое заголовка </ns2:AppHdr><ns3:Document xmlns:ns3 = "some other stuff"> содержимое документа </ns3:Document>
Обратите внимание, что все XML-дерево под AppHdr цитирует тег пространства имен AppHdr, а те, что под Document, цитируют тег Document.
Теги пространства имен могут различаться. В этом примере это ns2 и ns3, но какими они будут заранее я не знаю. Есть ли простой способ избавиться от них?
Это можно легко сделать через XSLT.
Почти каждый запрос на удаление пространств имен вызван непониманием их назначения и того, как с ними бороться. Имейте в виду, что вы отклоняетесь от рекомендуемого пути, удаляя пространства имен и, вероятно, создавая проблемы для себя и/или других людей, работающих с полученным XML-документом.
@kjhughes - Я слышу твое предупреждение. Мне интересно, что вы можете считать проблемой в приведенном выше примере. Я не уверен, как наличие двух разных пространств имен (и только иногда) повышает смысл документов.
Дело не в том, что я воспринимаю; дело в том, что компоненты XML (элементы и атрибуты) в пространстве имен XML намеренно имеют другие имена, чем те, которые не находятся в пространстве имен. Расстояние между именами служит нескольким целям, включая предотвращение конфликтов имен и установление полномочий для определения синтаксиса/семантики. Большинство запросов на их удаление связано с незнанием их назначения и/или механизма работы с ними, а не потому, что это лучшее дизайнерское решение в целом.





Минимальный воспроизводимый пример не приведен. Вот общее решение на основе XSLT, которое будет работать с любым правильно сформированным XML-файлом.
Входной XML
<root>
<ns2:AppHdr xmlns:ns2 = "some stuff">*contents of the header*</ns2:AppHdr>
<ns3:Document xmlns:ns3 = "some other stuff">*contents of the document*</ns3:Document>
</root>
XSLT
<?xml version='1.0'?>
<xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:output method = "xml" indent = "yes" omit-xml-declaration = "yes"/>
<xsl:strip-space elements = "*"/>
<!-- template to copy elements -->
<xsl:template match = "*">
<xsl:element name = "{local-name()}">
<xsl:apply-templates select = "@* | node()"/>
</xsl:element>
</xsl:template>
<!-- template to copy attributes -->
<xsl:template match = "@*">
<xsl:attribute name = "{local-name()}">
<xsl:value-of select = "."/>
</xsl:attribute>
</xsl:template>
<!-- template to copy the rest of the nodes -->
<xsl:template match = "comment() | text() | processing-instruction()">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
Выходной XML
<root>
<AppHdr>*contents of the header*</AppHdr>
<Document>*contents of the document*</Document>
</root>
С#
void Main()
{
const string SOURCEXMLFILE = @"e:\Temp\input.xml";
const string XSLTFILE = @"e:\Temp\process.xslt";
const string OUTPUTXMLFILE = @"e:\temp\output.xml";
try
{
XsltArgumentList xslArg = new XsltArgumentList();
using (XmlReader src = XmlReader.Create(SOURCEXMLFILE))
{
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(XSLTFILE, new XsltSettings(true, true), new XmlUrlResolver());
XmlWriterSettings settings = xslt.OutputSettings.Clone();
settings.IndentChars = "\t";
// to remove BOM
settings.Encoding = new UTF8Encoding(false);
using (XmlWriter result = XmlWriter.Create(OUTPUTXMLFILE, settings))
{
xslt.Transform(src, xslArg, result, new XmlUrlResolver());
result.Close();
}
}
Console.WriteLine("File '{0}' has been generated.", OUTPUTXMLFILE);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Привет @Yitzhak, спасибо за ответ. Я не могу легко привести минимальный рабочий пример, поскольку это означает вставку конфиденциальных финансовых данных, что мне явно не разрешено. Я не уверен, что строки пространства имен или структура сообщений Swift являются общедоступным, отсюда и минимальный характер вопроса. Спасибо за четкий и исчерпывающий ответ. Я буду использовать это. Очень признателен.
Задавая вопрос, вам необходимо предоставить минимальный воспроизводимый пример: Отредактируйте исходный вопрос и предоставьте следующее: (1) Образец правильно сформированного XML-файла. (2) Что вам нужно сделать, то есть логика, и ваш код пытается ее реализовать. (3) Желаемый результат основан на примере данных в № 1 выше.