How to unify redundant namespaces of an XML?

12

I have the following XML:

<?xml version="1.0" encoding="UTF-8"?>
<DataTable>
  <Columns>
    <DataColumn xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <ColumnName>NomeColuna1</ColumnName>
      <TypeName>System.String</TypeName>
    </DataColumn>
    <DataColumn xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <ColumnName>NomeColuna2</ColumnName>
      <TypeName>System.String</TypeName>
    </DataColumn>
    <DataColumn xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <ColumnName>NomeColuna3</ColumnName>
      <TypeName>System.Nullable'1[System.Decimal]</TypeName>
    </DataColumn>
    <DataColumn xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <ColumnName>NomeColunaN</ColumnName>
      <TypeName>System.Nullable'1[System.Decimal]</TypeName>
    </DataColumn>
  </Columns>
</DataTable>

Each <DataColumn> tag was previously generated from an individual serialization process.

At the end, all of these tags are enveloped in the <Columns> grouping tag during the actual XML write (I use, in this case, a XmlTextWriter ).

As I do not control the serialization of each <DataColumn> tag, the xmlns:i="http://www.w3.org/2001/XMLSchema-instance" namespace will be declared for each of them.

Is there a simple way, at the end of the final XML construct, to perform a cleanup to reduce redundancies? The result I hope would be:

<?xml version="1.0" encoding="UTF-8"?>
<DataTable xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Columns>
    <DataColumn>
      <ColumnName>NomeColuna1</ColumnName>
      <TypeName>System.String</TypeName>
    </DataColumn>
    <DataColumn>
      <ColumnName>NomeColuna2</ColumnName>
      <TypeName>System.String</TypeName>
    </DataColumn>
    <DataColumn>
      <ColumnName>NomeColuna3</ColumnName>
      <TypeName>System.Nullable'1[System.Decimal]</TypeName>
    </DataColumn>
    <DataColumn>
      <ColumnName>NomeColunaN</ColumnName>
      <TypeName>System.Nullable'1[System.Decimal]</TypeName>
    </DataColumn>
  </Columns>
</DataTable>
    
asked by anonymous 14.01.2014 / 14:50

1 answer

3

Well, assuming you write each XML fragment from a string to a XmlTextWriter , a way to remove the unwanted namespace, which will have no impact on the validity of the final XML, is to read the XML fragment and process it accordingly:

public static void WriteXml(XmlTextWriter writer, string xml) {
    var reader = XmlTextReader.Create(new StringReader(xml));
    while (reader.Read()) {
        WriteNode(writer, reader);
    }
}

private static void WriteNode(XmlTextWriter writer, XmlReader reader) {
    switch (reader.NodeType) {
        case XmlNodeType.Element: WriteStartElement(writer, reader); break;
        case XmlNodeType.EndElement: writer.WriteEndElement(); break;
        case XmlNodeType.Text: writer.WriteString(reader.Value); break;
        case XmlNodeType.Whitespace: writer.WriteWhitespace(reader.Value); break;
    }
}

private static void WriteStartElement(XmlTextWriter writer, XmlReader reader) {
    writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
    WriteAttributes(writer, reader);
}

private static void WriteAttributes(XmlTextWriter writer, XmlReader reader) {
    for (int i = 0; i < reader.AttributeCount; i++) {
        reader.MoveToAttribute(i);
        if (reader.Value == "http://www.w3.org/2001/XMLSchema-instance") continue;
        writer.WriteAttributeString(reader.Prefix, reader.LocalName, reader.NamespaceURI, reader.Value);
    }
    reader.MoveToElement();
}

Note that this code may not work with other XMLs. You pass each fragment in the xml parameter of the WriteXml method in a loop, always passing the same writer . Each fragment looks like:

<DataColumn xmlns:i='http://www.w3.org/2001/XMLSchema-instance'>
  <ColumnName>NomeColuna1</ColumnName>
  <TypeName>System.String</TypeName>
</DataColumn>

If this does not work with the code you have, please publish the relevant parts of the code that write XML fragments in XmlTextWriter .

    
16.01.2014 / 19:07