Làm cách nào để xóa tất cả các vùng tên khỏi XML với C #?


104

Tôi đang tìm kiếm giải pháp rõ ràng, thanh lịch và thông minh để xóa không gian tên khỏi tất cả các phần tử XML? Làm thế nào sẽ hoạt động để làm điều đó trông như thế nào?

Giao diện xác định:

public interface IXMLUtils
{
        string RemoveAllNamespaces(string xmlDocument);
}

Mẫu XML để xóa NS khỏi:

<?xml version="1.0" encoding="utf-16"?>
<ArrayOfInserts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <insert>
    <offer xmlns="http://schema.peters.com/doc_353/1/Types">0174587</offer>
    <type2 xmlns="http://schema.peters.com/doc_353/1/Types">014717</type2>
    <supplier xmlns="http://schema.peters.com/doc_353/1/Types">019172</supplier>
    <id_frame xmlns="http://schema.peters.com/doc_353/1/Types" />
    <type3 xmlns="http://schema.peters.com/doc_353/1/Types">
      <type2 />
      <main>false</main>
    </type3>
    <status xmlns="http://schema.peters.com/doc_353/1/Types">Some state</status>
  </insert>
</ArrayOfInserts>

Sau khi chúng ta gọi RemoveAllNamespaces (xmlWithLotOfNs), chúng ta sẽ nhận được:

  <?xml version="1.0" encoding="utf-16"?>
    <ArrayOfInserts>
      <insert>
        <offer >0174587</offer>
        <type2 >014717</type2>
        <supplier >019172</supplier>
        <id_frame  />
        <type3 >
          <type2 />
          <main>false</main>
        </type3>
        <status >Some state</status>
      </insert>
    </ArrayOfInserts>

Ngôn ngữ ưu tiên của giải pháp là C # trên .NET 3.5 SP1.


@JohnSaunders: Bạn nói đúng. Nhưng trường hợp cụ thể này tôi phải thực hiện một số tích hợp hệ thống. Và đây là lựa chọn duy nhất hồi đó.
Peter Stegnar

@PeterStegnar, lỗi thường là do hacker đã tạo ra các định dạng cũ. Thông thường, các nhà phát triển lạm dụng xml thường xuyên. Không gian tên là tính năng quan trọng điên rồ đầu tiên được gạt sang một bên.
Gusdor

Câu trả lời:


103

Vâng, đây là câu trả lời cuối cùng. Tôi đã sử dụng ý tưởng Jimmy tuyệt vời (không may là bản thân nó không hoàn chỉnh) và hoàn thành hàm đệ quy để hoạt động bình thường.

Dựa trên giao diện:

string RemoveAllNamespaces(string xmlDocument);

Tôi trình bày ở đây giải pháp C # sạch và phổ biến cuối cùng để xóa không gian tên XML:

//Implemented based on interface, not part of algorithm
public static string RemoveAllNamespaces(string xmlDocument)
{
    XElement xmlDocumentWithoutNs = RemoveAllNamespaces(XElement.Parse(xmlDocument));

    return xmlDocumentWithoutNs.ToString();
}

//Core recursion function
 private static XElement RemoveAllNamespaces(XElement xmlDocument)
    {
        if (!xmlDocument.HasElements)
        {
            XElement xElement = new XElement(xmlDocument.Name.LocalName);
            xElement.Value = xmlDocument.Value;

            foreach (XAttribute attribute in xmlDocument.Attributes())
                xElement.Add(attribute);

            return xElement;
        }
        return new XElement(xmlDocument.Name.LocalName, xmlDocument.Elements().Select(el => RemoveAllNamespaces(el)));
    }

Nó đang hoạt động 100%, nhưng tôi chưa thử nghiệm nhiều nên nó có thể không bao gồm một số trường hợp đặc biệt ... Nhưng đó là cơ sở tốt để bắt đầu.


8
Điều đó hoạt động tốt như thế nào với các thuộc tính có không gian tên? Trên thực tế, mã của bạn hoàn toàn bỏ qua các thuộc tính.
John Saunders

6
Tôi nhận ra rằng không gian tên có thể hữu ích trong một số ứng dụng, nhưng hoàn toàn không hữu ích với tôi; họ đã gây ra một sự khó chịu lớn. Giải pháp này đã làm việc cho tôi.
JYelton

@John Saunders - Vâng, tôi đã sử dụng giải pháp đó và tôi nhận ra rằng bạn đã đúng. Tôi đăng một giải pháp cập nhật như một câu trả lời
Konrad Morawski

6
Giải pháp này KHÔNG phù hợp với tôi, vì mã xóa tất cả các thuộc tính cũng như không gian tên. Tất nhiên, một vài thay đổi có thể làm việc để xem thuộc tính đang được gỡ bỏ là một không gian tên hoặc thuộc tính
bigfoot

@KonradMorawski, rất tiếc, tôi không thấy câu trả lời của bạn ở đây. :(
Rami A.

63

Câu trả lời hữu ích nhất được gắn thẻ có hai sai sót:

  • Nó bỏ qua các thuộc tính
  • Nó không hoạt động với các phần tử "chế độ hỗn hợp"

Đây là công việc của tôi:

 public static XElement RemoveAllNamespaces(XElement e)
 {
    return new XElement(e.Name.LocalName,
      (from n in e.Nodes()
        select ((n is XElement) ? RemoveAllNamespaces(n as XElement) : n)),
          (e.HasAttributes) ? 
            (from a in e.Attributes() 
               where (!a.IsNamespaceDeclaration)  
               select new XAttribute(a.Name.LocalName, a.Value)) : null);
  }          

Mã mẫu tại đây .


Thật không may, điều này không hiệu quả với tôi, xml tương tự đã nhập đã được trả lại. :(
Rami A.

@RamiA. bạn có thể đăng một đoạn mã để chúng tôi có thể xem vấn đề là gì không?
Dexter Legaspi

Cũng không hiệu quả với tôi. Tôi đoán vì bạn đang sao chép các thuộc tính mà bạn chỉ đơn giản là đang sao chép xmlns.
MarioDS

1
Những công việc này. Tôi đã sử dụng nó ... tuy nhiên tôi nhận ra rằng nó không được làm sạch hoàn toàn theo nghĩa là nó không loại bỏ các thuộc tính xmlns thực tế xác định không gian tên ... vì vậy tôi đã cập nhật nó để làm điều đó ... và thêm một ví dụ chính .
Dexter Legaspi

Cần thêm (from a in e.Attributes().DistinctBy(x => x.Name.LocalName)cho trường hợplang=""ru-ru"" xml:lang=""ru-ru""
smg

26

câu trả lời bắt buộc sử dụng LINQ:

static XElement stripNS(XElement root) {
    return new XElement(
        root.Name.LocalName,
        root.HasElements ? 
            root.Elements().Select(el => stripNS(el)) :
            (object)root.Value
    );
}
static void Main() {
    var xml = XElement.Parse(@"<?xml version=""1.0"" encoding=""utf-16""?>
    <ArrayOfInserts xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
      <insert>
        <offer xmlns=""http://schema.peters.com/doc_353/1/Types"">0174587</offer>
        <type2 xmlns=""http://schema.peters.com/doc_353/1/Types"">014717</type2>
        <supplier xmlns=""http://schema.peters.com/doc_353/1/Types"">019172</supplier>
        <id_frame xmlns=""http://schema.peters.com/doc_353/1/Types"" />
        <type3 xmlns=""http://schema.peters.com/doc_353/1/Types"">
          <type2 />
          <main>false</main>
        </type3>
        <status xmlns=""http://schema.peters.com/doc_353/1/Types"">Some state</status>
      </insert>
    </ArrayOfInserts>");
    Console.WriteLine(stripNS(xml));
}

3
Tôi đoán bạn có thể cho những người VB thấy rằng bạn có thể có một ký tự XML trong C # sau cùng.
Robert Harvey

1
@Robert, đó không phải là một chữ XML. Đó là một chuỗi. Có một sự khác biệt lớn!
CoderDennis

Jimmy, bạn đã gần nhưng vẫn chưa ở đó. :) Tôi đang viết giải pháp cuối cùng dựa trên ý tưởng của bạn. Tôi sẽ đăng nó ở đó.
Peter Stegnar

bạn đúng :) trong khi bạn đang ở đó, tôi cung cấp phiên bản sửa lỗi của riêng tôi.
Jimmy

3
Điều này loại bỏ tất cả các thuộc tính, không chỉ không gian tên. Xem câu trả lời của florian để biết cách khắc phục.
Brian

25

Điều đó sẽ làm các thủ thuật :-)

foreach (XElement XE in Xml.DescendantsAndSelf())
{
    // Stripping the namespace by setting the name of the element to it's localname only
    XE.Name = XE.Name.LocalName;
    // replacing all attributes with attributes that are not namespaces and their names are set to only the localname
    XE.ReplaceAttributes((from xattrib in XE.Attributes().Where(xa => !xa.IsNamespaceDeclaration) select new XAttribute(xattrib.Name.LocalName, xattrib.Value)));
}

Yo điều này hoạt động tuyệt vời, nó không chỉ hoạt động, nó thậm chí còn không ảnh hưởng đến tệp mà nó đang ghi dữ liệu cũng như Xelement bằng cách sử dụng phương thức DescendantAndself. cảm ơn người đàn ông!
shawn

làm việc cho tôi. Đồng thời xử lý CDATA mà các giải pháp khác bị mất trên đường đi.
paul

16

Nhặt lại lần nữa, trong C # - dòng thêm vào để sao chép các thuộc tính:

    static XElement stripNS(XElement root)
    {
        XElement res = new XElement(
            root.Name.LocalName,
            root.HasElements ?
                root.Elements().Select(el => stripNS(el)) :
                (object)root.Value
        );

        res.ReplaceAttributes(
            root.Attributes().Where(attr => (!attr.IsNamespaceDeclaration)));

        return res;
    }

1
Hoạt động cho phần tử gốc, nhưng không hoạt động cho phần tử lồng nhau; các không gian tên dường như chỉ được đổi tên, có thể tự động bởi XElement.ToString ().
Rami A.

Chính xác những gì tôi cần để loại bỏ tất cả các không gian tên, nhưng vẫn giữ các thuộc tính.
Bassie

10

Câu trả lời bắt buộc sử dụng XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="no" encoding="UTF-8"/>

  <xsl:template match="/|comment()|processing-instruction()">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*">
    <xsl:element name="{local-name()}">
      <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="@*">
    <xsl:attribute name="{local-name()}">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>

</xsl:stylesheet>

+1 cho "bắt buộc". :-) Tôi vẫn tự hỏi tại sao xóa không gian tên sẽ là một quyết định thông minh. Điều này có thể bị treo và cháy trên <element ns: attr = "a" attr = "b" />.
Tomalak

Ồ chắc chắn rồi, nhưng mọi kỹ thuật loại bỏ NS sẽ ở một mức độ lớn hơn hoặc ít hơn. Về tính hợp lệ, tôi có thể cho bạn biết nơi tôi cần nó: nhập XML của bên thứ ba, nơi họ không thể sắp xếp XSD hợp lệ nhưng nhấn mạnh vào không gian tên. Thực tiễn quy tắc cuối cùng.
annakata

1
@annakata: Giải pháp đơn giản hơn bạn nghĩ. Ngừng bật. Từ chối sử dụng bất kỳ kỹ thuật nào không hiểu XML. Lý do duy nhất mà chúng ta vẫn buộc phải sử dụng rác như vậy là vì mọi người luôn nói, "có", khi họ cần nói "không" thường xuyên hơn một chút. Các tiêu chuẩn đã hơn 10 năm tuổi! Tại sao chúng tôi vẫn có phần mềm không hiểu Không gian tên XML, ngoại trừ việc chúng tôi tiếp tục cho phép nó tồn tại?
John Saunders

3
@John - ha, có những điều nên làm, và có những điều mà ban quản lý cho là sẽ làm. Tất cả là vì điều tốt nhất trong những điều tốt nhất có thể.
annakata

1
@Tomalak một trường hợp sử dụng có thể là nếu bạn cần chuyển đổi sang JSON và các khai báo không gian tên can thiệp vào quá trình đó.
devlord

10

Và đây là giải pháp hoàn hảo cũng sẽ loại bỏ các phần tử XSI. (Nếu bạn xóa xmlns và không xóa XSI, .Net sẽ hét vào mặt bạn ...)

string xml = node.OuterXml;
//Regex below finds strings that start with xmlns, may or may not have :and some text, then continue with =
//and ", have a streach of text that does not contain quotes and end with ". similar, will happen to an attribute
// that starts with xsi.
string strXMLPattern = @"xmlns(:\w+)?=""([^""]+)""|xsi(:\w+)?=""([^""]+)""";
xml = Regex.Replace(xml, strXMLPattern, "");

1
Tôi nên đọc cái này 2 giờ trước. Đã gần như cùng một regex, điều duy nhất mà làm việc, trong XML phức tạp, với nhiều không gian tên, thuộc tính, vv
TPAKTOPA

Hãy nhớ rằng bạn vẫn có thể phải dọn dẹp các phần tử như <xxx: tagname> chẳng hạn. Tôi đã sử dụng mã sau (tuyên bố từ chối trách nhiệm, hoạt động trên máy của tôi): Regex.Replace(xmlStr, @"<(/?)([^>\s:]+):([^>]+)>", "<$1$3>")
Edwin

9

Tôi biết câu hỏi này được cho là đã được giải quyết, nhưng tôi không hoàn toàn hài lòng với cách nó được thực hiện. Tôi đã tìm thấy một nguồn khác ở đây trên các blog MSDN có ghi đèXmlTextWriter lớp được loại bỏ các không gian tên. Tôi đã chỉnh sửa nó một chút để có được một số thứ khác mà tôi muốn như định dạng đẹp và bảo toàn phần tử gốc. Đây là những gì tôi có trong dự án của mình vào lúc này.

http://blogs.msdn.com/b/kaevans/archive/2004/08/02/206432.aspx

Lớp học

/// <summary>
/// Modified XML writer that writes (almost) no namespaces out with pretty formatting
/// </summary>
/// <seealso cref="http://blogs.msdn.com/b/kaevans/archive/2004/08/02/206432.aspx"/>
public class XmlNoNamespaceWriter : XmlTextWriter
{
    private bool _SkipAttribute = false;
    private int _EncounteredNamespaceCount = 0;

    public XmlNoNamespaceWriter(TextWriter writer)
        : base(writer)
    {
        this.Formatting = System.Xml.Formatting.Indented;
    }

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
        base.WriteStartElement(null, localName, null);
    }

    public override void WriteStartAttribute(string prefix, string localName, string ns)
    {
        //If the prefix or localname are "xmlns", don't write it.
        //HOWEVER... if the 1st element (root?) has a namespace we will write it.
        if ((prefix.CompareTo("xmlns") == 0
                || localName.CompareTo("xmlns") == 0)
            && _EncounteredNamespaceCount++ > 0)
        {
            _SkipAttribute = true;
        }
        else
        {
            base.WriteStartAttribute(null, localName, null);
        }
    }

    public override void WriteString(string text)
    {
        //If we are writing an attribute, the text for the xmlns
        //or xmlns:prefix declaration would occur here.  Skip
        //it if this is the case.
        if (!_SkipAttribute)
        {
            base.WriteString(text);
        }
    }

    public override void WriteEndAttribute()
    {
        //If we skipped the WriteStartAttribute call, we have to
        //skip the WriteEndAttribute call as well or else the XmlWriter
        //will have an invalid state.
        if (!_SkipAttribute)
        {
            base.WriteEndAttribute();
        }
        //reset the boolean for the next attribute.
        _SkipAttribute = false;
    }

    public override void WriteQualifiedName(string localName, string ns)
    {
        //Always write the qualified name using only the
        //localname.
        base.WriteQualifiedName(localName, null);
    }
}

Sử dụng

//Save the updated document using our modified (almost) no-namespace XML writer
using(StreamWriter sw = new StreamWriter(this.XmlDocumentPath))
using(XmlNoNamespaceWriter xw = new XmlNoNamespaceWriter(sw))
{
    //This variable is of type `XmlDocument`
    this.XmlDocumentRoot.Save(xw);
}

1
Câu trả lời của bạn là câu trả lời duy nhất không cảm thấy giống như một cuộc tấn công, tuy nhiên, mẫu ban đầu trong bài đăng blog được tham chiếu chính xác hơn bởi vì nếu bạn không xóa không gian tên trong nút gốc, thì tất cả các nút và thuộc tính con không có không gian tên sẽ kế thừa không gian tên gốc.
giọng nam cao

8

Đây là một giải pháp dựa trên câu trả lời được chấp nhận của Peter Stegnar.

Tôi đã sử dụng nó, nhưng (như andygjp và John Saunders đã nhận xét) mã của anh ấy bỏ qua các thuộc tính .

Tôi cũng cần quan tâm đến các thuộc tính, vì vậy tôi đã điều chỉnh mã của anh ấy. Phiên bản của Andy là Visual Basic, đây vẫn là c #.

Tôi biết đã lâu rồi, nhưng có lẽ một ngày nào đó nó sẽ cứu được ai đó.

    private static XElement RemoveAllNamespaces(XElement xmlDocument)
    {
        XElement xmlDocumentWithoutNs = removeAllNamespaces(xmlDocument);
        return xmlDocumentWithoutNs;
    }

    private static XElement removeAllNamespaces(XElement xmlDocument)
    {
        var stripped = new XElement(xmlDocument.Name.LocalName);            
        foreach (var attribute in
                xmlDocument.Attributes().Where(
                attribute =>
                    !attribute.IsNamespaceDeclaration &&
                    String.IsNullOrEmpty(attribute.Name.NamespaceName)))
        {
            stripped.Add(new XAttribute(attribute.Name.LocalName, attribute.Value));
        }
        if (!xmlDocument.HasElements)
        {
            stripped.Value = xmlDocument.Value;
            return stripped;
        }
        stripped.Add(xmlDocument.Elements().Select(
            el =>
                RemoveAllNamespaces(el)));            
        return stripped;
    }

6

Tôi thực sự thích nơi Dexter sẽ đi lên đó vì vậy tôi đã dịch nó thành một phương thức mở rộng “trôi chảy”:

/// <summary>
/// Returns the specified <see cref="XElement"/>
/// without namespace qualifiers on elements and attributes.
/// </summary>
/// <param name="element">The element</param>
public static XElement WithoutNamespaces(this XElement element)
{
    if (element == null) return null;

    #region delegates:

        Func<XNode, XNode> getChildNode = e => (e.NodeType == XmlNodeType.Element) ? (e as XElement).WithoutNamespaces() : e;

        Func<XElement, IEnumerable<XAttribute>> getAttributes = e => (e.HasAttributes) ?
            e.Attributes()
                .Where(a => !a.IsNamespaceDeclaration)
                .Select(a => new XAttribute(a.Name.LocalName, a.Value))
            :
            Enumerable.Empty<XAttribute>();

        #endregion

    return new XElement(element.Name.LocalName,
        element.Nodes().Select(getChildNode),
        getAttributes(element));
}

Phương pháp tiếp cận "thông thạo" cho phép tôi làm điều này:

var xml = File.ReadAllText(presentationFile);
var xDoc = XDocument.Parse(xml);
var xRoot = xDoc.Root.WithoutNamespaces();

1
Cảm ơn cho giải pháp này! Hoạt động tốt cho vấn đề của tôi.
AngieM

1
Vì vậy, điều này là lý tưởng VÌ nó hoạt động trên các thuộc tính. Có thể sử dụng điều này mà không có vấn đề gì. Cảm ơn
guppy Julian

4

Bạn có thể làm điều đó bằng Linq:

public static string RemoveAllNamespaces(string xmlDocument)
{
    var xml = XElement.Parse(xmlDocument);
    xml.Descendants().Select(o => o.Name = o.Name.LocalName).ToArray();
    return xml.ToString();
}

3

Câu trả lời của Peter đã được sửa đổi một chút, điều này cũng sẽ hoạt động tốt cho thuộc tính, bao gồm cả việc xóa không gian tên và tiền tố. Một chút xin lỗi vì mã trông hơi xấu xí.

 private static XElement RemoveAllNamespaces(XElement xmlDocument)
        {
            if (!xmlDocument.HasElements)
            {
                XElement xElement = new XElement(xmlDocument.Name.LocalName);
                xElement.Value = xmlDocument.Value;

                foreach (XAttribute attribute in xmlDocument.Attributes())
                {
                    xElement.Add(new XAttribute(attribute.Name.LocalName, attribute.Value));
                }

                return xElement;
            }

            else
            {
                XElement xElement = new XElement(xmlDocument.Name.LocalName,  xmlDocument.Elements().Select(el => RemoveAllNamespaces(el)));

                foreach (XAttribute attribute in xmlDocument.Attributes())
                {
                    xElement.Add(new XAttribute(attribute.Name.LocalName, attribute.Value));
                }

                return xElement;
            }

    }

+1 Điều này đã làm việc cho tôi. Tuy nhiên, nó để lại các thuộc tính là một phần của định nghĩa không gian tên (chỉ xóa tiền tố xmlns) nhưng chúng hiện không ảnh hưởng đến việc tuần tự hóa.
Rami A.

2

Câu trả lời của Jimmy và Peter là một sự trợ giúp tuyệt vời, nhưng họ thực sự đã loại bỏ tất cả các thuộc tính, vì vậy tôi đã thực hiện một sửa đổi nhỏ:

Imports System.Runtime.CompilerServices

Friend Module XElementExtensions

    <Extension()> _
    Public Function RemoveAllNamespaces(ByVal element As XElement) As XElement
        If element.HasElements Then
            Dim cleanElement = RemoveAllNamespaces(New XElement(element.Name.LocalName, element.Attributes))
            cleanElement.Add(element.Elements.Select(Function(el) RemoveAllNamespaces(el)))
            Return cleanElement
        Else
            Dim allAttributesExceptNamespaces = element.Attributes.Where(Function(attr) Not attr.IsNamespaceDeclaration)
            element.ReplaceAttributes(allAttributesExceptNamespaces)
            Return element
        End If

    End Function

End Module

2

Đến bữa tiệc muộn một chút nhưng đây là những gì tôi đã sử dụng gần đây:

var doc = XDocument.Parse(xmlString);
doc.Root.DescendantNodesAndSelf().OfType<XElement>().Attributes().Where(att => att.IsNamespaceDeclaration).Remove();

(lấy từ MSDN Thread này )

Chỉnh sửa Theo nhận xét bên dưới, có vẻ như trong khi điều này loại bỏ tiền tố không gian tên khỏi các nút, nó không thực sự loại bỏ thuộc tính xmlns. Để làm điều đó, bạn cũng cần đặt lại tên của mỗi nút thành tên cục bộ của nó (ví dụ: tên trừ không gian tên)

foreach (var node in doc.Root.DescendantNodesAndSelf().OfType<XElement>())
{
    node.Name = node.Name.LocalName;
}

Dường như không hoạt động? Nó tìm thấy tất cả các khai báo không gian tên, nhưng việc gọi Remove () trên tập hợp đó không làm được gì cả. Tôi đã thử result.ToString () và chuỗi kết quả vẫn có thuộc tính xmlns. Tôi có làm điều gì sai?
Jimmy

Nó hoạt động cho những gì tôi cần vào thời điểm đó nhưng bây giờ tôi nhìn lại nó không phải là 100%. Nó loại bỏ các tiền tố không gian tên khỏi các nút (đó là những gì tôi cần) nhưng bạn nói đúng về việc nó để lại thuộc tính xmlns. Thật kỳ lạ, thuộc tính đó cũng không được nhận dạng bởi bất kỳ phương thức XDocument nào!
MarcE

1

Để các thuộc tính hoạt động, vòng lặp for để thêm thuộc tính phải đi sau đệ quy, cũng cần kiểm tra xem IsNamespaceDec Tuyên bố:

private static XElement RemoveAllNamespaces(XElement xmlDocument)
{
    XElement xElement;

    if (!xmlDocument.HasElements)
    {
        xElement = new XElement(xmlDocument.Name.LocalName) { Value = xmlDocument.Value };
    }
    else
    {
        xElement = new XElement(xmlDocument.Name.LocalName, xmlDocument.Elements().Select(RemoveAllNamespaces));
    }

    foreach (var attribute in xmlDocument.Attributes())
    {
        if (!attribute.IsNamespaceDeclaration)
        {
            xElement.Add(attribute);
        }
    }

    return xElement;
}

1

Đây là phiên bản VB.NET của tôi về Phiên bản Dexter Legaspi C #

Shared Function RemoveAllNamespaces(ByVal e As XElement) As XElement
        Return New XElement(e.Name.LocalName, New Object() {(From n In e.Nodes Select If(TypeOf n Is XElement, RemoveAllNamespaces(TryCast(n, XElement)), n)), If(e.HasAttributes, (From a In e.Attributes Select a), Nothing)})
End Function

1

Một giải pháp khác có tính đến khả năng xen kẽ các nút TEXT và ELEMENT, ví dụ:

<parent>
    text1
    <child1/>
    text2
    <child2/>
</parent>

Mã:

using System.Linq;

namespace System.Xml.Linq
{
    public static class XElementTransformExtensions
    {
        public static XElement WithoutNamespaces(this XElement source)
        {
            return new XElement(source.Name.LocalName,
                source.Attributes().Select(WithoutNamespaces),
                source.Nodes().Select(WithoutNamespaces)
            );
        }

        public static XAttribute WithoutNamespaces(this XAttribute source)
        {
            return !source.IsNamespaceDeclaration
                ? new XAttribute(source.Name.LocalName, source.Value)
                : default(XAttribute);
        }

        public static XNode WithoutNamespaces(this XNode source)
        {
            return
                source is XElement
                    ? WithoutNamespaces((XElement)source)
                    : source;
        }
    }
}

1

Không cần dùng đến giải pháp dựa trên XSLT, nếu bạn muốn sạch sẽ, trang nhã và thông minh, bạn sẽ cần một số hỗ trợ từ khung, đặc biệt, mẫu khách truy cập có thể giúp việc này trở nên dễ dàng. Thật không may, nó không có sẵn ở đây.

Tôi đã thực hiện nó lấy cảm hứng từ LINQ ExpressionVisitorđể có cấu trúc tương tự như nó. Với điều này, bạn có thể áp dụng mẫu khách truy cập cho các đối tượng XML (LINQ-to-). (Tôi đã thực hiện thử nghiệm giới hạn về điều này nhưng nó hoạt động tốt theo như tôi có thể nói)

public abstract class XObjectVisitor
{
    public virtual XObject Visit(XObject node)
    {
        if (node != null)
            return node.Accept(this);
        return node;
    }

    public ReadOnlyCollection<XObject> Visit(IEnumerable<XObject> nodes)
    {
        return nodes.Select(node => Visit(node))
            .Where(node => node != null)
            .ToList()
            .AsReadOnly();
    }

    public T VisitAndConvert<T>(T node) where T : XObject
    {
        if (node != null)
            return Visit(node) as T;
        return node;
    }

    public ReadOnlyCollection<T> VisitAndConvert<T>(IEnumerable<T> nodes) where T : XObject
    {
        return nodes.Select(node => VisitAndConvert(node))
            .Where(node => node != null)
            .ToList()
            .AsReadOnly();
    }

    protected virtual XObject VisitAttribute(XAttribute node)
    {
        return node.Update(node.Name, node.Value);
    }

    protected virtual XObject VisitComment(XComment node)
    {
        return node.Update(node.Value);
    }

    protected virtual XObject VisitDocument(XDocument node)
    {
        return node.Update(
            node.Declaration,
            VisitAndConvert(node.Nodes())
        );
    }

    protected virtual XObject VisitElement(XElement node)
    {
        return node.Update(
            node.Name,
            VisitAndConvert(node.Attributes()),
            VisitAndConvert(node.Nodes())
        );
    }

    protected virtual XObject VisitDocumentType(XDocumentType node)
    {
        return node.Update(
            node.Name,
            node.PublicId,
            node.SystemId,
            node.InternalSubset
        );
    }

    protected virtual XObject VisitProcessingInstruction(XProcessingInstruction node)
    {
        return node.Update(
            node.Target,
            node.Data
        );
    }

    protected virtual XObject VisitText(XText node)
    {
        return node.Update(node.Value);
    }

    protected virtual XObject VisitCData(XCData node)
    {
        return node.Update(node.Value);
    }

    #region Implementation details
    internal InternalAccessor Accessor
    {
        get { return new InternalAccessor(this); }
    }

    internal class InternalAccessor
    {
        private XObjectVisitor visitor;
        internal InternalAccessor(XObjectVisitor visitor) { this.visitor = visitor; }

        internal XObject VisitAttribute(XAttribute node) { return visitor.VisitAttribute(node); }
        internal XObject VisitComment(XComment node) { return visitor.VisitComment(node); }
        internal XObject VisitDocument(XDocument node) { return visitor.VisitDocument(node); }
        internal XObject VisitElement(XElement node) { return visitor.VisitElement(node); }
        internal XObject VisitDocumentType(XDocumentType node) { return visitor.VisitDocumentType(node); }
        internal XObject VisitProcessingInstruction(XProcessingInstruction node) { return visitor.VisitProcessingInstruction(node); }
        internal XObject VisitText(XText node) { return visitor.VisitText(node); }
        internal XObject VisitCData(XCData node) { return visitor.VisitCData(node); }
    }
    #endregion
}

public static class XObjectVisitorExtensions
{
    #region XObject.Accept "instance" method
    public static XObject Accept(this XObject node, XObjectVisitor visitor)
    {
        Validation.CheckNullReference(node);
        Validation.CheckArgumentNull(visitor, "visitor");

        // yay, easy dynamic dispatch
        Acceptor acceptor = new Acceptor(node as dynamic);
        return acceptor.Accept(visitor);
    }
    private class Acceptor
    {
        public Acceptor(XAttribute node) : this(v => v.Accessor.VisitAttribute(node)) { }
        public Acceptor(XComment node) : this(v => v.Accessor.VisitComment(node)) { }
        public Acceptor(XDocument node) : this(v => v.Accessor.VisitDocument(node)) { }
        public Acceptor(XElement node) : this(v => v.Accessor.VisitElement(node)) { }
        public Acceptor(XDocumentType node) : this(v => v.Accessor.VisitDocumentType(node)) { }
        public Acceptor(XProcessingInstruction node) : this(v => v.Accessor.VisitProcessingInstruction(node)) { }
        public Acceptor(XText node) : this(v => v.Accessor.VisitText(node)) { }
        public Acceptor(XCData node) : this(v => v.Accessor.VisitCData(node)) { }

        private Func<XObjectVisitor, XObject> accept;
        private Acceptor(Func<XObjectVisitor, XObject> accept) { this.accept = accept; }

        public XObject Accept(XObjectVisitor visitor) { return accept(visitor); }
    }
    #endregion

    #region XObject.Update "instance" method
    public static XObject Update(this XAttribute node, XName name, string value)
    {
        Validation.CheckNullReference(node);
        Validation.CheckArgumentNull(name, "name");
        Validation.CheckArgumentNull(value, "value");

        return new XAttribute(name, value);
    }
    public static XObject Update(this XComment node, string value = null)
    {
        Validation.CheckNullReference(node);

        return new XComment(value);
    }
    public static XObject Update(this XDocument node, XDeclaration declaration = null, params object[] content)
    {
        Validation.CheckNullReference(node);

        return new XDocument(declaration, content);
    }
    public static XObject Update(this XElement node, XName name, params object[] content)
    {
        Validation.CheckNullReference(node);
        Validation.CheckArgumentNull(name, "name");

        return new XElement(name, content);
    }
    public static XObject Update(this XDocumentType node, string name, string publicId = null, string systemId = null, string internalSubset = null)
    {
        Validation.CheckNullReference(node);
        Validation.CheckArgumentNull(name, "name");

        return new XDocumentType(name, publicId, systemId, internalSubset);
    }
    public static XObject Update(this XProcessingInstruction node, string target, string data)
    {
        Validation.CheckNullReference(node);
        Validation.CheckArgumentNull(target, "target");
        Validation.CheckArgumentNull(data, "data");

        return new XProcessingInstruction(target, data);
    }
    public static XObject Update(this XText node, string value = null)
    {
        Validation.CheckNullReference(node);

        return new XText(value);
    }
    public static XObject Update(this XCData node, string value = null)
    {
        Validation.CheckNullReference(node);

        return new XCData(value);
    }
    #endregion
}

public static class Validation
{
    public static void CheckNullReference<T>(T obj) where T : class
    {
        if (obj == null)
            throw new NullReferenceException();
    }

    public static void CheckArgumentNull<T>(T obj, string paramName) where T : class
    {
        if (obj == null)
            throw new ArgumentNullException(paramName);
    }
}

ps, việc triển khai cụ thể này sử dụng một số tính năng .NET 4 để làm cho việc triển khai dễ dàng / sạch sẽ hơn một chút (sử dụng dynamicvà các đối số mặc định). Không quá khó để làm cho nó tương thích với .NET 3.5, thậm chí có thể tương thích với .NET 2.0.

Sau đó, để triển khai khách truy cập, đây là một cách tổng quát có thể thay đổi nhiều không gian tên (và tiền tố được sử dụng).

public class ChangeNamespaceVisitor : XObjectVisitor
{
    private INamespaceMappingManager manager;
    public ChangeNamespaceVisitor(INamespaceMappingManager manager)
    {
        Validation.CheckArgumentNull(manager, "manager");

        this.manager = manager;
    }

    protected INamespaceMappingManager Manager { get { return manager; } }

    private XName ChangeNamespace(XName name)
    {
        var mapping = Manager.GetMapping(name.Namespace);
        return mapping.ChangeNamespace(name);
    }

    private XObject ChangeNamespaceDeclaration(XAttribute node)
    {
        var mapping = Manager.GetMapping(node.Value);
        return mapping.ChangeNamespaceDeclaration(node);
    }

    protected override XObject VisitAttribute(XAttribute node)
    {
        if (node.IsNamespaceDeclaration)
            return ChangeNamespaceDeclaration(node);
        return node.Update(ChangeNamespace(node.Name), node.Value);
    }

    protected override XObject VisitElement(XElement node)
    {
        return node.Update(
            ChangeNamespace(node.Name),
            VisitAndConvert(node.Attributes()),
            VisitAndConvert(node.Nodes())
        );
    }
}

// and all the gory implementation details
public class NamespaceMappingManager : INamespaceMappingManager
{
    private Dictionary<XNamespace, INamespaceMapping> namespaces = new Dictionary<XNamespace, INamespaceMapping>();

    public NamespaceMappingManager Add(XNamespace fromNs, XNamespace toNs, string toPrefix = null)
    {
        var item = new NamespaceMapping(fromNs, toNs, toPrefix);
        namespaces.Add(item.FromNs, item);
        return this;
    }

    public INamespaceMapping GetMapping(XNamespace fromNs)
    {
        INamespaceMapping mapping;
        if (!namespaces.TryGetValue(fromNs, out mapping))
            mapping = new NullMapping();
        return mapping;
    }

    private class NullMapping : INamespaceMapping
    {
        public XName ChangeNamespace(XName name)
        {
            return name;
        }

        public XObject ChangeNamespaceDeclaration(XAttribute node)
        {
            return node.Update(node.Name, node.Value);
        }
    }

    private class NamespaceMapping : INamespaceMapping
    {
        private XNamespace fromNs;
        private XNamespace toNs;
        private string toPrefix;
        public NamespaceMapping(XNamespace fromNs, XNamespace toNs, string toPrefix = null)
        {
            this.fromNs = fromNs ?? "";
            this.toNs = toNs ?? "";
            this.toPrefix = toPrefix;
        }

        public XNamespace FromNs { get { return fromNs; } }
        public XNamespace ToNs { get { return toNs; } }
        public string ToPrefix { get { return toPrefix; } }

        public XName ChangeNamespace(XName name)
        {
            return name.Namespace == fromNs
                ? toNs + name.LocalName
                : name;
        }

        public XObject ChangeNamespaceDeclaration(XAttribute node)
        {
            if (node.Value == fromNs.NamespaceName)
            {
                if (toNs == XNamespace.None)
                    return null;
                var xmlns = !String.IsNullOrWhiteSpace(toPrefix)
                    ? (XNamespace.Xmlns + toPrefix)
                    : node.Name;
                return node.Update(xmlns, toNs.NamespaceName);
            }
            return node.Update(node.Name, node.Value);
        }
    }
}

public interface INamespaceMappingManager
{
    INamespaceMapping GetMapping(XNamespace fromNs);
}

public interface INamespaceMapping
{
    XName ChangeNamespace(XName name);
    XObject ChangeNamespaceDeclaration(XAttribute node);
}

Và một phương pháp trợ giúp nhỏ để bóng lăn:

T ChangeNamespace<T>(T node, XNamespace fromNs, XNamespace toNs, string toPrefix = null) where T : XObject
{
    return node.Accept(
        new ChangeNamespaceVisitor(
            new NamespaceMappingManager()
                .Add(fromNs, toNs, toPrefix)
        )
    ) as T;
}

Sau đó, để loại bỏ một không gian tên, bạn có thể gọi nó như vậy:

var doc = ChangeNamespace(XDocument.Load(pathToXml),
    fromNs: "http://schema.peters.com/doc_353/1/Types",
    toNs: null);

Sử dụng khách truy cập này, bạn có thể viết một INamespaceMappingManagerđể xóa tất cả các không gian tên.

T RemoveAllNamespaces<T>(T node) where T : XObject
{
    return node.Accept(
        new ChangeNamespaceVisitor(new RemoveNamespaceMappingManager())
    ) as T;
}

public class RemoveNamespaceMappingManager : INamespaceMappingManager
{
    public INamespaceMapping GetMapping(XNamespace fromNs)
    {
        return new RemoveNamespaceMapping();
    }

    private class RemoveNamespaceMapping : INamespaceMapping
    {
        public XName ChangeNamespace(XName name)
        {
            return name.LocalName;
        }

        public XObject ChangeNamespaceDeclaration(XAttribute node)
        {
            return null;
        }
    }
}

1

Giải pháp đơn giản thực sự đổi tên các phần tử tại chỗ, không tạo bản sao và thực hiện khá tốt việc thay thế các thuộc tính.

public void RemoveAllNamespaces(ref XElement value)
{
  List<XAttribute> attributesToRemove = new List<XAttribute>();
  foreach (void e_loopVariable in value.DescendantsAndSelf) {
    e = e_loopVariable;
    if (e.Name.Namespace != XNamespace.None) {
      e.Name = e.Name.LocalName;
    }
    foreach (void a_loopVariable in e.Attributes) {
      a = a_loopVariable;
      if (a.IsNamespaceDeclaration) {
        //do not keep it at all
        attributesToRemove.Add(a);
      } else if (a.Name.Namespace != XNamespace.None) {
        e.SetAttributeValue(a.Name.LocalName, a.Value);
        attributesToRemove.Add(a);
      }
    }
  }
  foreach (void a_loopVariable in attributesToRemove) {
    a = a_loopVariable;
    a.Remove();
  }
}

Lưu ý: điều này không phải lúc nào cũng bảo toàn thứ tự thuộc tính ban đầu, nhưng tôi chắc chắn rằng bạn có thể thay đổi nó để thực hiện điều đó khá dễ dàng nếu nó quan trọng với bạn.

Cũng lưu ý rằng điều này cũng có thể tạo ra một ngoại lệ, nếu bạn có một thuộc tính XElement chỉ là duy nhất với không gian tên, như:

<root xmlns:ns1="a" xmlns:ns2="b">
    <elem ns1:dupAttrib="" ns2:dupAttrib="" />
</root>

mà thực sự có vẻ như là một vấn đề cố hữu. Nhưng vì câu hỏi đã chỉ ra việc đưa ra một Chuỗi chứ không phải XElement, trong trường hợp này, bạn có thể có một giải pháp để xuất ra một Chuỗi hợp lệ là XElement không hợp lệ.

Tôi cũng thích câu trả lời của jocull bằng cách sử dụng XmlWriter tùy chỉnh, nhưng khi tôi thử nó, nó không hoạt động với tôi. Mặc dù tất cả trông đúng, tôi không thể nói nếu lớp XmlNoNamespaceWriter có bất kỳ ảnh hưởng nào cả; nó chắc chắn không loại bỏ các không gian tên như tôi muốn.


1

Thêm của tôi mà cũng làm sạch tên của các nút có tiền tố không gian tên:

    public static string RemoveAllNamespaces(XElement element)
    {
        string tex = element.ToString();
        var nsitems = element.DescendantsAndSelf().Select(n => n.ToString().Split(' ', '>')[0].Split('<')[1]).Where(n => n.Contains(":")).DistinctBy(n => n).ToArray();

        //Namespace prefix on nodes: <a:nodename/>
        tex = nsitems.Aggregate(tex, (current, nsnode) => current.Replace("<"+nsnode + "", "<" + nsnode.Split(':')[1] + ""));
        tex = nsitems.Aggregate(tex, (current, nsnode) => current.Replace("</" + nsnode + "", "</" + nsnode.Split(':')[1] + ""));

        //Namespace attribs
        var items = element.DescendantsAndSelf().SelectMany(d => d.Attributes().Where(a => a.IsNamespaceDeclaration || a.ToString().Contains(":"))).DistinctBy(o => o.Value);
        tex = items.Aggregate(tex, (current, xAttribute) => current.Replace(xAttribute.ToString(), ""));

        return tex;
    }

1

Tôi đã thử một số giải pháp đầu tiên và không hiệu quả với tôi. Chủ yếu là vấn đề với các thuộc tính bị loại bỏ như các thuộc tính khác đã được đề cập. Tôi có thể nói rằng cách tiếp cận của tôi rất giống với Jimmy bằng cách sử dụng các hàm tạo XElement lấy đối tượng làm tham số.

public static XElement RemoveAllNamespaces(this XElement element)
{
    return new XElement(element.Name.LocalName,
                        element.HasAttributes ? element.Attributes().Select(a => new XAttribute(a.Name.LocalName, a.Value)) : null,
                        element.HasElements ? element.Elements().Select(e => RemoveAllNamespaces(e)) : null,
                        element.Value);
}

1

câu trả lời của tôi, dựa trên thao tác chuỗi,
mã đơn giản nhất,

public static string hilangkanNamespace(string instrXML)
    {
        char chrOpeningTag = '<';
        char chrClosingTag = '>';
        char chrSpasi = ' ';
        int intStartIndex = 0;
        do
        {
            int intIndexKu = instrXML.IndexOf(chrOpeningTag, intStartIndex);
            if (intIndexKu < 0)
                break; //kalau dah ga ketemu keluar
            int intStart = instrXML.IndexOfAny(new char[] { chrSpasi, chrClosingTag }, intIndexKu + 1); //mana yang ketemu duluan
            if (intStart < 0)
                break; //kalau dah ga ketemu keluar
            int intStop = instrXML.IndexOf(chrClosingTag, intStart);
            if (intStop < 0)
                break; //kalau dah ga ketemu keluar
            else
                intStop--; //exclude si closingTag
            int intLengthToStrip = intStop - intStart + 1;
            instrXML = instrXML.Remove(intStart, intLengthToStrip);
            intStartIndex = intStart;
        } while (true);

        return instrXML;
    }

1

Đây là Regex Thay thế một lớp lót:

public static string RemoveNamespaces(this string xml)
{
    return Regex.Replace(xml, "((?<=<|<\\/)|(?<= ))[A-Za-z0-9]+:| xmlns(:[A-Za-z0-9]+)?=\".*?\"", "");
}

Đây là mẫu: https://regex101.com/r/fopydN/6

Cảnh báo: có thể có các trường hợp cạnh!


0

Câu trả lời của user892217 gần như đúng. Nó sẽ không biên dịch như hiện tại, vì vậy cần sửa một chút đối với lời gọi đệ quy:

private static XElement RemoveAllNamespaces(XElement xmlDocument)
{
    XElement xElement;

    if (!xmlDocument.HasElements)
    {
        xElement = new XElement(xmlDocument.Name.LocalName) { Value = xmlDocument.Value };
    }
    else
    {
        xElement = new XElement(xmlDocument.Name.LocalName, xmlDocument.Elements().Select(x => RemoveAllNamespaces(x)));
    }

    foreach (var attribute in xmlDocument.Attributes())
    {
        if (!attribute.IsNamespaceDeclaration)
        {
            xElement.Add(attribute);
        }
    }

    return xElement;
}

0

Điều này đã làm việc cho tôi.

       FileStream fs = new FileStream(filePath, FileMode.Open);

       StreamReader sr = new StreamReader(fs);

        DataSet ds = new DataSet();
        ds.ReadXml(sr);
        ds.Namespace = "";

        string outXML = ds.GetXml();
        ds.Dispose();
        sr.Dispose();
        fs.Dispose();

0

Sau nhiều lần tìm kiếm giải pháp cho vấn đề này, trang cụ thể này dường như có nhiều thứ nhất ... tuy nhiên, không có gì hoàn toàn phù hợp chính xác, vì vậy tôi đã làm theo cách cũ và chỉ phân tích nội dung tôi muốn ra. Hy vọng điều này sẽ giúp ai đó. (Lưu ý: điều này cũng loại bỏ SOAP hoặc những thứ tương tự trên phong bì.)

        public static string RemoveNamespaces(string psXml)
    {
        //
        // parse through the passed XML, and remove any and all namespace references...also
        // removes soap envelope/header(s)/body, or any other references via ":" entities,
        // leaving all data intact
        //
        string xsXml = "", xsCurrQtChr = "";
        int xiPos = 0, xiLastPos = psXml.Length - 1;
        bool xbInNode = false;

        while (xiPos <= xiLastPos)
        {
            string xsCurrChr = psXml.Substring(xiPos, 1);
            xiPos++;
            if (xbInNode)
            {
                if (xsCurrChr == ":")
                {
                    // soap envelope or body (or some such)
                    // we'll strip these node wrappers completely
                    // need to first strip the beginning of it off  (i.e. "<soap" or "<s")
                    int xi = xsXml.Length;
                    string xsChr = "";
                    do
                    {
                        xi--;
                        xsChr = xsXml.Substring(xi, 1);
                        xsXml = xsXml.Substring(0, xi);
                    } while (xsChr != "<");

                    // next, find end of node
                    string xsQt = "";
                    do
                    {
                        xiPos++;
                        if (xiPos <= xiLastPos)
                        {
                            xsChr = psXml.Substring(xiPos, 1);
                            if (xsQt.Length == 0)
                            {
                                if (xsChr == "'" || xsChr == "\"")
                                {
                                    xsQt = xsChr;
                                }
                            }
                            else
                            {
                                if (xsChr == xsQt)
                                {
                                    xsQt = "";  // end of quote
                                }
                                else
                                {
                                    if (xsChr == ">") xsChr = "x";      // stay in loop...this is not end of node
                                }
                            }
                        }
                    } while (xsChr != ">" && xiPos <= xiLastPos);
                    xiPos++;            // skip over closing ">"
                    xbInNode = false;
                }
                else
                {
                    if (xsCurrChr == ">")
                    {
                        xbInNode = false;
                        xsXml += xsCurrChr;
                    }
                    else
                    {
                        if (xsCurrChr == " " || xsCurrChr == "\t")
                        {
                            // potential namespace...let's check...next character must be "/"
                            // or more white space, and if not, skip until we find such
                            string xsChr = "";
                            int xiOrgLen = xsXml.Length;
                            xsXml += xsCurrChr;
                            do
                            {
                                if (xiPos <= xiLastPos)
                                {
                                    xsChr = psXml.Substring(xiPos, 1);
                                    xiPos++;
                                    if (xsChr == " " || xsChr == "\r" || xsChr == "\n" || xsChr == "\t")
                                    {
                                        // carry on..white space
                                        xsXml += xsChr;
                                    }
                                    else
                                    {
                                        if (xsChr == "/" || xsChr == ">")
                                        {
                                            xsXml += xsChr;
                                        }
                                        else
                                        {
                                            // namespace! - get rid of it
                                            xsXml = xsXml.Substring(0, xiOrgLen - 0);       // first, truncate any added whitespace
                                            // next, peek forward until we find "/" or ">"
                                            string xsQt = "";
                                            do
                                            {
                                                if (xiPos <= xiLastPos)
                                                {
                                                    xsChr = psXml.Substring(xiPos, 1);
                                                    xiPos++;
                                                    if (xsQt.Length > 0)
                                                    {
                                                        if (xsChr == xsQt) xsQt = ""; else xsChr = "x";
                                                    }
                                                    else
                                                    {
                                                        if (xsChr == "'" || xsChr == "\"") xsQt = xsChr;
                                                    }
                                                }
                                            } while (xsChr != ">" && xsChr != "/" && xiPos <= xiLastPos);
                                            if (xsChr == ">" || xsChr == "/") xsXml += xsChr;
                                            xbInNode = false;
                                        }
                                    }
                                }
                            } while (xsChr != ">" && xsChr != "/" && xiPos <= xiLastPos);
                        }
                        else
                        {
                            xsXml += xsCurrChr;
                        }
                    }
                }
            }
            else
            {
                //
                // if not currently inside a node, then we are in a value (or about to enter a new node)
                //
                xsXml += xsCurrChr;
                if (xsCurrQtChr.Length == 0)
                {
                    if (xsCurrChr == "<")
                    {
                        xbInNode = true;
                    }
                }
                else
                {
                    //
                    // currently inside a quoted string
                    //
                    if (xsCurrQtChr == xsCurrChr)
                    {
                        // finishing quoted string
                        xsCurrQtChr = "";
                    }
                }
            }
        }

        return (xsXml);
    }

0

Nếu không tạo lại toàn bộ hệ thống phân cấp nút:

private static void RemoveDefNamespace(XElement element)
{
    var defNamespase = element.Attribute("xmlns");
    if (defNamespase != null)
        defNamespase.Remove();

    element.Name = element.Name.LocalName;
    foreach (var child in element.Elements())
    {
        RemoveDefNamespace(child);
    }
}

0

Tôi đã thử một số giải pháp, nhưng như nhiều người đã nêu, có một số trường hợp khó.

Đã sử dụng một số regex ở trên, nhưng đi đến kết luận rằng regex một bước là không khả thi.

Vì vậy, đây là giải pháp của tôi, regex 2 bước, tìm thẻ, loại bỏ thẻ bên trong, không thay đổi cdata:

            Func<Match, String> NamespaceRemover = delegate (Match match)
            {
                var result = match.Value;
                if (String.IsNullOrEmpty(match.Groups["cdata"].Value))
                {
                    // find all prefixes within start-, end tag and attributes and also namespace declarations
                    return Regex.Replace(result, "((?<=<|<\\/| ))\\w+:| xmlns(:\\w+)?=\".*?\"", "");
                }
                else
                {
                    // cdata as is
                    return result;
                }
            };
            // XmlDocument doc;
            // string file;
            doc.LoadXml(
              Regex.Replace(File.ReadAllText(file), 
                // find all begin, cdata and end tags (do not change order)
                @"<(?:\w+:?\w+.*?|(?<cdata>!\[CDATA\[.*?\]\])|\/\w+:?\w+)>", 
                new MatchEvaluator(NamespaceRemover)
              )
            );

Hiện tại, nó đang làm việc 100% cho tôi.


-1

Đây là một giải pháp dựa trên regex cho vấn đề này ...

    private XmlDocument RemoveNS(XmlDocument doc)
    {
        var xml = doc.OuterXml;
        var newxml = Regex.Replace(xml, @"xmlns[:xsi|:xsd]*="".*?""","");
        var newdoc = new XmlDocument();
        newdoc.LoadXml(newxml);
        return newdoc;
    }

-1

Tôi nghĩ đây là câu trả lời ngắn nhất (nhưng đối với các hằng số như, bạn sẽ có một cuộc thảo luận khác, tôi cũng có regex để chuyển đổi "<bcm:info></bcm:info>"thành " <info></info>" nhưng nó không được tối ưu hóa, Nếu ai đó hỏi tôi, tôi sẽ chia sẻ nó. Vì vậy, giải pháp của tôi là:

    public string RemoveAllNamespaces(string xmlDocument)
    {
        return Regex.Replace(xmlDocument, @"\sxmlns(\u003A\w+)?\u003D\u0022.+\u0022", " ");
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.