c# - XPath को XElement में प्राप्त करें?




xml (6)

मुझे एक दस्तावेज़ के भीतर एक XElement गहरा मिला है। XElement (और XDocument?) को देखते हुए, क्या इसका पूर्ण (यानी पूर्ण, उदाहरण /root/item/element/child ) XPath प्राप्त करने के लिए एक विस्तार विधि है?

जैसे myXElement.GetXPath ()?

संपादित करें: ठीक है, ऐसा लगता है कि मैंने कुछ बहुत महत्वपूर्ण देखा है। ओह! तत्व की अनुक्रमणिका को ध्यान में रखा जाना चाहिए। प्रस्तावित सही समाधान के लिए मेरा अंतिम उत्तर देखें।


"पूर्ण xpath" से मुझे लगता है कि आप टैग की एक साधारण श्रृंखला का मतलब है क्योंकि xpaths की संख्या जो किसी भी तत्व से संभावित रूप से मेल खा सकती है, बहुत बड़ी हो सकती है।

यहां समस्या यह है कि अगर यह किसी भी दिए गए xpath को बनाने के लिए विशेष रूप से असंभव नहीं है तो यह बहुत कठिन है जो एक ही तत्व पर वापस आ जाएगा - क्या यह एक शर्त है?

यदि "नहीं" तो शायद आप वर्तमान तत्व parentNode के संदर्भ में रिकर्सिव लूपिंग द्वारा एक क्वेरी बना सकते हैं। यदि "हां" है, तो आप सिब्लिंग सेट के भीतर इंडेक्स स्थिति के लिए क्रॉस रेफरेंसिंग द्वारा विस्तारित होने जा रहे हैं, यदि वे मौजूद हैं तो आईडी-जैसी विशेषताओं को रेफर कर रहे हैं, और यदि यह एक सामान्य समाधान है तो यह आपके एक्सएसडी पर बहुत निर्भर होगा संभव है।


एक अलग परियोजना के हिस्से के रूप में मैंने एक तत्व के लिए एक सरल XPath उत्पन्न करने के लिए एक विस्तार विधि विकसित की। यह चयनित उत्तर के समान है, लेकिन XElement के अलावा XAttribute, XText, XCData और XComment का समर्थन करता है। यह कोड nuget , प्रोजेक्ट पेज के रूप में यहां उपलब्ध है: xmlspecificationcompare.codeplex.com


कई एक्सपैथ हो सकते हैं जो एक ही तत्व को जन्म देते हैं, इसलिए सबसे आसान xpath ढूंढना जो नोड की ओर जाता है वह छोटा नहीं होता है।

उस ने कहा, नोड को xpath ढूंढना काफी आसान है। जब तक आप रूट नोड पढ़ते हैं और नोड नामों को गठबंधन करते हैं तब तक नोड पेड़ को ऊपर उठाएं और आपके पास वैध xpath है।


माइक्रोसॉफ्ट ने ऐसा करने के लिए एक विस्तार विधि प्रदान की है क्योंकि .NET Framework 3.5:

http://msdn.microsoft.com/en-us/library/bb156083(v=vs.100).aspx

बस System.Xml.XPath एक उपयोग जोड़ें और निम्न विधियों का आह्वान करें:

  • XPathSelectElement : एकल तत्व का चयन करें
  • XPathSelectElements : तत्वों का चयन करें और एक XPathSelectElements IEnumerable<XElement> रूप में वापस आएं
  • XPathEvaluate : नोड्स का चयन करें (न केवल तत्व, बल्कि पाठ, टिप्पणियां इत्यादि) और एक IEnumerable<object>

मैंने क्रिस द्वारा कोड नामस्थान उपसर्गों को ध्यान में रखने के लिए कोड अपडेट किया। केवल GetAbsoluteXPath विधि संशोधित की गई है।

public static class XExtensions
{
    /// <summary>
    /// Get the absolute XPath to a given XElement, including the namespace.
    /// (e.g. "/a:people/b:person[6]/c:name[1]/d:last[1]").
    /// </summary>
    public static string GetAbsoluteXPath(this XElement element)
    {
        if (element == null)
        {
            throw new ArgumentNullException("element");
        }

        Func<XElement, string> relativeXPath = e =>
        {
            int index = e.IndexPosition();

            var currentNamespace = e.Name.Namespace;

            string name;
            if (currentNamespace == null)
            {
                name = e.Name.LocalName;
            }
            else
            {
                string namespacePrefix = e.GetPrefixOfNamespace(currentNamespace);
                name = namespacePrefix + ":" + e.Name.LocalName;
            }

            // If the element is the root, no index is required
            return (index == -1) ? "/" + name : string.Format
            (
                "/{0}[{1}]",
                name,
                index.ToString()
            );
        };

        var ancestors = from e in element.Ancestors()
                        select relativeXPath(e);

        return string.Concat(ancestors.Reverse().ToArray()) +
               relativeXPath(element);
    }

    /// <summary>
    /// Get the index of the given XElement relative to its
    /// siblings with identical names. If the given element is
    /// the root, -1 is returned.
    /// </summary>
    /// <param name="element">
    /// The element to get the index of.
    /// </param>
    public static int IndexPosition(this XElement element)
    {
        if (element == null)
        {
            throw new ArgumentNullException("element");
        }

        if (element.Parent == null)
        {
            return -1;
        }

        int i = 1; // Indexes for nodes start at 1, not 0

        foreach (var sibling in element.Parent.Elements(element.Name))
        {
            if (sibling == element)
            {
                return i;
            }

            i++;
        }

        throw new InvalidOperationException
            ("element has been removed from its parent.");
    }
}

यदि आप .NET द्वारा प्रदान की गई कुछ चीज़ों की तलाश में हैं तो उत्तर नहीं है। ऐसा करने के लिए आपको अपनी खुद की विस्तार विधि लिखनी होगी।





xelement