LINQ में XML में नामस्थान पर ध्यान न दें


87

मेरे पास LINQ to XML iqnore सभी नामस्थान कैसे हैं? या बदलकर, मैं कैसे नामस्थानों को छीन सकता हूं?

मैं पूछ रहा हूं क्योंकि नामस्थान एक अर्ध-यादृच्छिक फैशन में सेट किए जा रहे हैं और मैं बिना नाम के दोनों के साथ नोड्स की खोज करने के लिए थक गया हूं।


जवाबों:


137

लिखने के बजाय:

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']

यदि आप जानते हैं कि आप जिस तत्व को चाहते हैं, उसका नाम विशिष्ट है, तो आप सभी मध्यवर्ती तत्वों को छोड़ सकते हैं:xDoc.Root.Descendants().Where(e => e.Name.LocalName == "SomeName");
AaronLS

17

यहां नामस्थानों को पट्टी करने की एक विधि दी गई है:

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

4

जैसा कि मैंने विशेषताओं पर नामस्थानों को अनदेखा करने के आसान तरीके की तलाश में यह प्रश्न पाया, यहाँ एक विशेषता तक पहुँचने पर नामस्थानों की अनदेखी करने के लिए एक एक्सटेंशन है, जो पावेल्स के उत्तर पर आधारित है (आसान प्रतिलिपि के लिए, मैंने उनका एक्सटेंशन शामिल किया है):

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);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.