programing

LINQ에서 XML로 네임스페이스 무시

javajsp 2023. 10. 6. 20:53

LINQ에서 XML로 네임스페이스 무시

모든 네임스페이스를 LINQ에서 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);
}

속성의 경우, 네임스피드 속성을 자주 처리해야 하는 경우(상대적으로 드문 경우) Ditto.

[EDIT] 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);
}

언급URL : https://stackoverflow.com/questions/1145659/ignore-namespaces-in-linq-to-xml