C #을 사용하여 XML에서 모든 네임 스페이스를 제거하는 방법은 무엇입니까?


104

모든 XML 요소에서 네임 스페이스를 제거하는 깨끗하고 우아하며 스마트 한 솔루션을 찾고 있습니까? 그게 어떻게 생겼을까 요?

정의 된 인터페이스 :

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

NS를 제거하기위한 샘플 XML :

<?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>

RemoveAllNamespaces (xmlWithLotOfNs)를 호출 한 후 다음을 가져와야합니다.

  <?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>

기본 솔루션 언어는 .NET 3.5 SP1의 C #입니다.


@JohnSaunders : 당신 말이 맞아요. 하지만이 특별한 경우에는 시스템 통합을해야합니다. 그리고 이것은 당시 유일한 선택이었습니다.
Peter Stegnar

@PeterStegnar 오류는 일반적으로 레거시 형식을 만든 해커입니다. 종종 개발자는 xml을 만성적으로 오용합니다. 네임 스페이스는 버려 질 첫 번째 미친 중요한 기능입니다.
Gusdor

답변:


103

음, 여기에 최종 답변이 있습니다. 나는 훌륭한 Jimmy 아이디어 (불행히도 자체가 완전하지 않음)와 완전한 재귀 함수를 사용하여 제대로 작동했습니다.

인터페이스 기반 :

string RemoveAllNamespaces(string xmlDocument);

여기서는 XML 네임 스페이스를 제거하기위한 최종적이고 보편적 인 C # 솔루션을 나타냅니다.

//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)));
    }

100 % 작동하지만 많은 테스트를 거치지 않았기 때문에 일부 특수한 경우를 다루지 않을 수도 있습니다.하지만 시작하기에 좋은 기준입니다.


8
네임 스페이스가있는 속성과 얼마나 잘 작동합니까? 실제로 코드는 속성을 완전히 무시합니다.
John Saunders

6
네임 스페이스가 일부 애플리케이션에서는 유용 할 수 있지만 내에서는 전혀 유용하지 않다는 것을 알고 있습니다. 그들은 엄청난 성가심을 불러 일으켰습니다. 이 솔루션은 저에게 효과적이었습니다.
JYelton 2010 년

@John Saunders-네, 그 솔루션을 사용했고 당신이 옳다는 것을 깨달았습니다. 업데이트 된 솔루션을 답변으로 게시하고 있습니다
Konrad Morawski 2011 년

6
코드가 모든 속성과 네임 스페이스를 제거하기 때문에이 솔루션은 저에게 효과적이지 않았습니다. 물론, 제거되는 속성이 네임 스페이스 또는 속성인지 확인하기 위해 몇 가지 변경 사항이
적용될 수 있습니다

@KonradMorawski, 불행히도 여기에 귀하의 답변이 표시되지 않습니다. :(
Rami A.

63

태그가 지정된 가장 유용한 답변에는 두 가지 결함이 있습니다.

  • 속성을 무시합니다.
  • "혼합 모드"요소에서는 작동하지 않습니다.

이것에 대한 나의 견해는 다음과 같습니다.

 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);
  }          

여기에 샘플 코드가 있습니다 .


불행히도 이것은 나를 위해 작동하지 않았으며 입력 한 동일한 xml이 반환되었습니다. :(
Rami A.

@RamiA. 문제가 무엇인지 알 수 있도록 코드 스 니펫을 게시 할 수 있습니까?
Dexter Legaspi 2013

나에게도 작동하지 않았습니다. 나는 당신이 속성을 복사하고 있기 때문에 단순히 복사하는 것 xmlns같습니다.
MarioDS 2014-06-19

1
작동합니다. 나는 그것을 사용했습니다 ... 그러나 네임 스페이스를 정의하는 실제 xmlns 속성을 제거하지 않는다는 의미에서 철저한 정리가 아니라는 것을 깨달았습니다 ... 그래서 그것을 업데이트하고 요점 예제를 추가했습니다. .
Dexter Legaspi

(from a in e.Attributes().DistinctBy(x => x.Name.LocalName)케이스 추가 필요lang=""ru-ru"" xml:lang=""ru-ru""
smg 2015-10-27

26

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
결국 C #에서 XML 리터럴을 가질 수있는 VB 사람들을 보여줄 수 있다고 생각합니다.
Robert Harvey

1
@Robert, 그것은 XML 리터럴이 아닙니다. 문자열입니다. 큰 차이가 있습니다!
CoderDennis

지미, 당신은 가깝지만 아직 거기에 있지 않습니다. :) 귀하의 아이디어를 바탕으로 최종 솔루션을 작성하고 있습니다. 거기에 게시하겠습니다.
Peter Stegnar

당신이 옳습니다 :) 당신이 그것에있는 동안 나는 수정의 내 버전을 제공합니다.
Jimmy

3
이것은 네임 스페이스뿐만 아니라 모든 속성을 제거합니다. 수정을 위해 florian의 대답 을 참조하십시오 .
Brian

25

그것은 트릭을 할 것입니다 :-)

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 이것은 훌륭하게 작동하고 작동 할뿐만 아니라 DescendantAndself 메서드를 사용하여 데이터를 쓰는 파일에도 영향을 미치지 않습니다. 감사합니다!
shawn dec

나를 위해 작동합니다. 또한 다른 솔루션이 느슨해지는 CDATA도 처리합니다.
paul

16

C #에서 다시 선택-속성 복사를위한 줄 추가 :

    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
루트 요소에 대해 작동하지만 중첩 된 요소에는 작동하지 않습니다. 네임 스페이스는 XElement.ToString ()에 의해 자동으로 이름이 변경된 것 같습니다.
Rami A.

모든 네임 스페이스를 제거하는 데 정확히 필요한 것이지만 속성은 유지합니다.
Bassie

10

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. :-) 왜 네임 스페이스를 제거하는 것이 현명한 결정인지 궁금합니다. 이것은 아마도 <element ns : attr = "a"attr = "b"/>에서 충돌하고 번질 수 있습니다.
Tomalak

물론입니다.하지만 모든 NS 제거 기술은 어느 정도는 될 것입니다. 또는 타당성으로, 내가 필요한 곳을 알려줄 수 있습니다. 유효한 XSD를 분류 할 수 없지만 네임 스페이스를 고집하는 타사 XML 가져 오기. 궁극적으로 실용성 규칙.
annakata

1
@annakata : 해결책은 생각보다 간단합니다. 활성화를 중지하십시오. XML을 이해하지 못하는 기술은 사용하지 마십시오. 우리가 여전히 그런 쓰레기를 사용하도록 강요받는 유일한 이유는 사람들이 "아니오"라고 조금 더 자주 말할 필요가있을 때 "예"라고 계속해서 말하기 때문입니다. 표준은 10 년이 넘었습니다! XML 네임 스페이스를 계속해서 사용할 수 있다는 점을 제외하고는 여전히 XML 네임 스페이스를 이해하지 못하는 소프트웨어가있는 이유는 무엇입니까?
John Saunders

3
@John-하,해야 할 일이 있고 경영진이 할 것이라고 생각하는 일이 있습니다. 모든 것은 가능한 모든 세계에서 최고를위한 것입니다.
annakata 2009-06-15

1
@Tomalak 사용 사례 중 하나는 JSON으로 변환해야하고 네임 스페이스 선언이 해당 프로세스를 방해하는 경우 일 수 있습니다.
devlord

10

그리고 이것은 XSI 요소도 제거하는 완벽한 솔루션입니다. (xmlns를 제거하고 XSI를 제거하지 않으면 .Net이 소리 친다 ...)

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
2 시간 전에 읽어야 겠어요. 복잡한 XML에서 많은 네임 스페이스, 속성 등을 사용하여 거의 동일한 정규식을 사용했습니다.
TPAKTOPA

여전히 <xxx : tagname>과 같은 요소를 정리해야 할 수도 있습니다. 다음 코드를 사용했습니다 (면책 조항, 내 컴퓨터에서 작동). Regex.Replace(xmlStr, @"<(/?)([^>\s:]+):([^>]+)>", "<$1$3>")
Edwin

9

이 질문이 해결 된 것으로 알고 있지만 구현 방식에 완전히 만족하지 않았습니다. 재정의 된 MSDN 블로그에서 다른 소스를 찾았습니다.XmlTextWriter네임 스페이스를 제거 클래스 . 예쁜 서식 지정 및 루트 요소 보존과 같이 내가 원하는 다른 것들을 얻기 위해 약간 조정했습니다. 현재 내 프로젝트에있는 내용은 다음과 같습니다.

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

수업

/// <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);
    }
}

용법

//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
귀하의 답변은 해킹처럼 느껴지지 않는 유일한 답변이지만 참조 된 블로그 게시물의 원본 샘플이 더 정확합니다. 루트 노드에서 네임 스페이스를 제거하지 않으면 모든 하위 노드와 속성이 네임 스페이스는 루트 네임 스페이스를 상속합니다.
테너

8

이것은 Peter Stegnar의 대답을 기반으로 한 솔루션입니다.

나는 그것을 사용했지만 (andygjp와 John Saunders가 언급했듯이) 그의 코드 는 속성을 무시합니다 .

속성도 관리해야했기 때문에 코드를 수정했습니다. Andy의 버전은 Visual Basic 이었지만 여전히 C #입니다.

오랜만이라는 건 알지만 언젠가는 누군가의 시간을 절약 할 수있을 것입니다.

    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

덱스터 가 올라가는 곳이 정말 마음에 들어서 "유창한"확장 방법으로 번역했습니다.

/// <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));
}

"유창한"접근 방식을 통해 다음을 수행 할 수 있습니다.

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

1
이 솔루션에 감사드립니다! 내 문제에 잘 맞습니다.
AngieM

1
그래서 이것은 속성에 작용했기 때문에 이상적이었습니다. 이것을 문제없이 사용할 수있었습니다. 감사합니다
줄리안 붕어

4

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

Peter의 대답을 약간 수정하면 네임 스페이스와 접두사 제거를 포함하여 특성에 대해서도 잘 작동합니다. 코드가 약간 못 생겼습니다.

 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 이것은 나를 위해 일했습니다. 그러나 네임 스페이스 정의의 일부인 속성 (xmlns 접두사 만 제거됨)은 남겨 두지 만 현재 직렬화에는 영향을주지 않습니다.
Rami A.

2

Jimmy와 Peter의 답변은 큰 도움이되었지만 실제로 모든 속성을 제거했기 때문에 약간 수정했습니다.

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

이 파티에 조금 늦었지만 최근에 사용한 내용은 다음과 같습니다.

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

(이 MSDN 스레드 에서 가져옴 )

편집 아래 설명에 따라 노드에서 네임 스페이스 접두사를 제거하지만 실제로 xmlns 속성을 제거하지 않는 것으로 보입니다. 이를 위해서는 각 노드의 이름을 로컬 이름으로 재설정해야합니다 (예 : 이름에서 네임 스페이스를 뺀 이름).

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

작동하지 않는 것 같습니까? 모든 네임 스페이스 선언을 찾지 만 해당 컬렉션에서 Remove ()를 호출해도 아무 작업도 수행되지 않습니다. result.ToString ()을 시도했지만 결과 문자열에는 여전히 xmlns 속성이 있습니다. 내가 뭘 잘못하고 있니?
Jimmy

당시에 필요한만큼 효과가 있었지만 지금은 100 %가 아닙니다. 노드에서 네임 스페이스 접두사 (내가 필요로하는 것)를 제거하지만 xmlns 속성을 남겨 두는 것이 맞습니다. 이상하게도이 속성은 XDocument 메서드에서도 인식되지 않습니다!
MarcE

1

속성이 작동하려면 속성을 추가하기위한 for 루프가 재귀 후에 이동해야하며 IsNamespaceDeclaration이 있는지 확인해야합니다.

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

다음은 Dexter Legaspi C # 버전의 VB.NET 버전입니다.

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

TEXT 및 ELEMENT 노드의 인터리빙 가능성을 고려하는 또 다른 솔루션입니다. 예 :

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

암호:

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

XSLT 기반 솔루션에 의존하지 않고 깨끗하고 우아하고 스마트 한 경우 프레임 워크의 지원이 필요합니다. 특히 방문자 패턴이이를 쉽게 만들 수 있습니다. 안타깝게도 여기에서는 사용할 수 없습니다.

ExpressionVisitor비슷한 구조를 갖도록 LINQ에서 영감을 받아 구현 했습니다. 이를 통해 방문자 패턴을 (LINQ-to-) XML 개체에 적용 할 수 있습니다. (나는 이것에 대해 제한된 테스트를 수행했지만 내가 말할 수있는 한 잘 작동합니다)

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);
    }
}

추신,이 특정 구현은 일부 .NET 4 기능을 사용하여 구현을 좀 더 쉽고 / 깨끗하게 만듭니다 (사용 dynamic 및 기본 인수 사용). .NET 3.5와 호환되도록 만드는 것이 너무 어렵지 않아야합니다. 아마도 .NET 2.0 과도 호환됩니다.

그런 다음 방문자를 구현하기 위해 여러 네임 스페이스 (및 사용 된 접두사)를 변경할 수있는 일반화 된 방문자가 있습니다.

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);
}

그리고 공을 굴리는 작은 도우미 방법 :

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;
}

그런 다음 네임 스페이스를 제거하려면 다음과 같이 호출 할 수 있습니다.

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

이 방문자를 사용하여 INamespaceMappingManager모든 네임 스페이스를 제거하기 위해를 작성할 수 있습니다 .

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

복사본을 만들지 않고 실제로 요소의 이름을 변경하고 속성을 대체하는 작업을 수행하는 간단한 솔루션입니다.

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();
  }
}

참고 : 이것이 항상 원래 속성 순서를 유지하는 것은 아니지만 중요한 경우이를 매우 쉽게 수행하도록 변경할 수 있습니다.

또한이 또한주의 할 수 네임 스페이스 같은에서만 고유 XElement를 속성이 있다면, 예외를 throw :

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

본질적인 문제처럼 보입니다. 그러나 질문은 XElement가 아닌 String을 출력하는 것으로 나타났기 때문에이 경우 잘못된 XElement 인 유효한 String을 출력하는 솔루션을 가질 수 있습니다.

나는 또한 사용자 정의 XmlWriter를 사용하는 jocull의 대답을 좋아했지만 시도했을 때 작동하지 않았습니다. 모든 것이 정확 해 보이지만 XmlNoNamespaceWriter 클래스가 어떤 영향을 미쳤는지 알 수 없었습니다. 내가 원했던대로 네임 스페이스를 제거하지 않았 음이 분명합니다.


1

my를 추가하면 네임 스페이스 접두사가있는 노드의 이름도 정리됩니다.

    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

나는 처음 몇 가지 해결책을 시도했지만 나를 위해 일하지 않았습니다. 주로 이미 언급 한 것처럼 속성이 제거되는 문제입니다. 개체를 매개 변수로 사용하는 XElement 생성자를 사용하여 내 접근 방식이 Jimmy와 매우 유사하다고 말할 수 있습니다.

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

내 대답, 문자열 조작 기반,
가장 가벼운 코드,

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

다음은 Regex Replace one liner입니다.

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

다음은 샘플입니다. https://regex101.com/r/fopydN/6

경고 : 엣지 케이스가있을 수 있습니다!


0

user892217의 대답은 거의 정확합니다. 그대로 컴파일되지 않으므로 재귀 호출을 약간 수정해야합니다.

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

이것은 나를 위해 일했습니다.

       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

이 문제에 대한 해결책을 많이 찾고 나서이 특정 페이지에 가장 많은 내용이 포함되어있는 것 같았지만 정확히 맞는 것은 없었기 때문에 구식 방식을 사용하여 원하는 내용을 분석했습니다. 이것이 누군가를 돕기를 바랍니다. (참고 : 이것은 또한 SOAP 또는 유사한 봉투 항목을 제거합니다.)

        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

전체 노드 계층 구조를 다시 만들지 않고 :

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

몇 가지 솔루션을 시도했지만 많은 사람들이 언급했듯이 몇 가지 가장자리 사례가 있습니다.

위의 정규식 중 일부를 사용했지만 한 단계 정규식이 실현 불가능하다는 결론에 도달했습니다.

그래서 여기 내 솔루션, 2 단계 정규식, 태그 찾기, 태그 제거 내에서 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)
              )
            );

지금은 100 % 효과가 있습니다.


-1

다음은이 문제에 대한 정규식 기반 솔루션입니다.

    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

나는 이것이 가장 짧은 대답이라고 생각합니다 (그러나와 같은 구성의 경우 다른 토론이있을 것입니다. 또한 "<bcm:info></bcm:info>"" <info></info>" 로 변환 할 정규식이 있지만 최적화되지 않았습니다. 누군가 내게 물어 보면 공유하겠습니다. 그래서 내 해결책은 다음과 같습니다.

    public string RemoveAllNamespaces(string xmlDocument)
    {
        return Regex.Replace(xmlDocument, @"\sxmlns(\u003A\w+)?\u003D\u0022.+\u0022", " ");
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.