[.net] LINQ to XML에서 네임 스페이스 무시

LINQ to XML iqnore 모든 네임 스페이스를 사용하려면 어떻게해야합니까? 또는 네임 스페이스를 제거하는 방법은 무엇입니까?

네임 스페이스가 반 무작위 방식으로 설정되고 네임 스페이스가 있거나없는 노드를 모두 검색해야하는 데 지 쳤기 때문에 질문하고 있습니다.



답변

작성하는 대신 :

nodes.Elements("Foo")

쓰다:

nodes.Elements().Where(e => e.Name.LocalName == "Foo")

질리면 자신 만의 확장 방법을 만드세요.

public static IEnumerable<XElement> ElementsAnyNS<T>(this IEnumerable<T> source, string localName)
    where T : XContainer
{
    return source.Elements().Where(e => e.Name.LocalName == localName);
}

네임 스페이스 속성을 자주 처리해야하는 경우 (비교적 드문 경우 임) 속성도 마찬가지입니다.

[편집] XPath에 대한 솔루션 추가

XPath의 경우 작성하는 대신 :

/foo/bar | /foo/ns:bar | /ns:foo/bar | /ns:foo/ns:bar

local-name()기능 을 사용할 수 있습니다 .

/*[local-name() = 'foo']/*[local-name() = 'bar']


답변

다음은 네임 스페이스를 제거하는 방법입니다.

private static XElement StripNamespaces(XElement rootElement)
{
    foreach (var element in rootElement.DescendantsAndSelf())
    {
        // update element name if a namespace is available
        if (element.Name.Namespace != XNamespace.None)
        {
            element.Name = XNamespace.None.GetName(element.Name.LocalName);
        }

        // check if the element contains attributes with defined namespaces (ignore xml and empty namespaces)
        bool hasDefinedNamespaces = element.Attributes().Any(attribute => attribute.IsNamespaceDeclaration ||
                (attribute.Name.Namespace != XNamespace.None && attribute.Name.Namespace != XNamespace.Xml));

        if (hasDefinedNamespaces)
        {
            // ignore attributes with a namespace declaration
            // strip namespace from attributes with defined namespaces, ignore xml / empty namespaces
            // xml namespace is ignored to retain the space preserve attribute
            var attributes = element.Attributes()
                                    .Where(attribute => !attribute.IsNamespaceDeclaration)
                                    .Select(attribute =>
                                        (attribute.Name.Namespace != XNamespace.None && attribute.Name.Namespace != XNamespace.Xml) ?
                                            new XAttribute(XNamespace.None.GetName(attribute.Name.LocalName), attribute.Value) :
                                            attribute
                                    );

            // replace with attributes result
            element.ReplaceAttributes(attributes);
        }
    }
    return rootElement;
}

사용 예 :

XNamespace ns = "http://schemas.domain.com/orders";
XElement xml =
    new XElement(ns + "order",
        new XElement(ns + "customer", "Foo", new XAttribute("hello", "world")),
        new XElement("purchases",
            new XElement(ns + "purchase", "Unicycle", new XAttribute("price", "100.00")),
            new XElement("purchase", "Bicycle"),
            new XElement(ns + "purchase", "Tricycle",
                new XAttribute("price", "300.00"),
                new XAttribute(XNamespace.Xml.GetName("space"), "preserve")
            )
        )
    );

Console.WriteLine(xml.Element("customer") == null);
Console.WriteLine(xml);
StripNamespaces(xml);
Console.WriteLine(xml);
Console.WriteLine(xml.Element("customer").Attribute("hello").Value);


답변

속성에 대한 네임 스페이스를 무시하는 쉬운 방법을 찾기 위해이 질문을 찾았으므로 여기 Pavel의 답변을 기반으로 속성에 액세스 할 때 네임 스페이스를 무시하는 확장이 있습니다 (더 쉽게 복사하기 위해 그의 확장을 포함했습니다).

public static XAttribute AttributeAnyNS<T>(this T source, string localName)
where T : XElement
{
    return source.Attributes().SingleOrDefault(e => e.Name.LocalName == localName);
}

public static IEnumerable<XElement> ElementsAnyNS<T>(this IEnumerable<T> source, string localName)
where T : XContainer
{
    return source.Elements().Where(e => e.Name.LocalName == localName);
}


답변