2011-02-07 14 views
6

मैं मेनू के भीतर कुछ नोड्स को बाहर करने के लिए XPath का उपयोग कर रहा हूं। मैं एक सरणी में पहचाने गए नोड्स को बाहर करने के लिए इस पर विस्तार करना चाहता हूं।मैं string.Format के भीतर सरणी मानों का संदर्भ कैसे दूं?

XmlNodeList nextLevelNodeList = currentNode 
            .SelectNodes(string 
                .Format(" 
              Menu[not(MenuId = 2905)] 
               /Item[ 
               ItemLevel = {0} 
                and 
               ItemType != 'Javascript' 
               ] | 
              Menu[MenuId = 2905] 
               /Item[ 
               ItemLevel = {0} 
                and 
               ItemType = 'content' 
               ]", iLevel)); 

मैं चाहता क्या एक सरणी में menuId और कई अन्य लोगों की दुकान और फिर संदर्भ लेने के लिए है:

इस आईडी 2905 जिसका प्रकार के साथ मेनू में सभी नोड्स निकालने का कार्य करता सामग्री नहीं है String.Format समारोह

कुछ की तरह भीतर सरणी:

int[] excludeSubmenus = {2905, 323}; 
XmlNodeList nextLevelNodeList = currentNode 
            .SelectNodes(string 
                .Format(" 
             Menu[not(MenuId in excludesubMenus)] 
              /Item[ 
               ItemLevel={0} 
                and 
               ItemType != 'Javascript' 
              ] | 
             Menu[MenuId in excludeSubMenus] 
              /Item[ 
               ItemLevel={0} 
                and 
               ItemType='content' 
              ]", iLevel)); 

किसी भी सलाह बहुत सराहना की जाएगी! -

टा नाथन

संपादित उदाहरण एक्सएमएल

<Item> 
    <ItemId>322</ItemId> 
    <ItemType>Submenu</ItemType> 
    <ItemLevel>2</ItemLevel> 
    <Menu> 
     <MenuId>322</MenuId> 
     <MenuLevel>2</MenuLevel> 
     <Item> 
      <ItemId>2905</ItemId> 
      <ItemType>Submenu</ItemType> 
      <ItemLevel>3</ItemLevel> 
      <Menu> 
       <MenuId>2905</MenuId> 
       <MenuLevel>3</MenuLevel> 
       <Item> 
        <ItemId>19196</ItemId> 
        <ItemType>content</ItemType> 
        <ItemLevel>4</ItemLevel> 
       </Item> 
       <Item> 
        <ItemId>19192</ItemId> 
        <ItemType>Submenu</ItemType> 
        <ItemLevel>4</ItemLevel> 
       </Item> 
      </Menu> 
     </Item> 
     <Item> 
      <ItemId>2906</ItemId> 
      <ItemType>Submenu</ItemType> 
      <ItemLevel>3</ItemLevel> 
      <Menu> 
       <MenuId>323</MenuId> 
       <MenuLevel>3</MenuLevel> 
       <Item> 
        <ItemId>2432</ItemId> 
        <ItemType>content</ItemType> 
        <ItemLevel>4</ItemLevel> 
       </Item> 
       <Item> 
        <ItemId>12353</ItemId> 
        <ItemType>Submenu</ItemType> 
        <ItemLevel>4</ItemLevel> 
       </Item> 
      </Menu> 
     </Item> 
    </Menu> 
</Item> 
+0

अच्छा प्रश्न, +1। एक पूर्ण और आसान समाधान के लिए मेरा जवाब देखें। :) –

+0

क्लासिक "अनुक्रम में मौजूद" XPath 1.0 अभिव्यक्ति के लिए मेरा उत्तर देखें। –

उत्तर

1

उपयोग में शामिल हैं:

int[] excludeSubmenus = {2905, 323}; 

string notExpr = string.Empty; 

for(int i=0; i < excludeSubmenus.Length; i++) 
    { 
    notExpr += string.Format("not(MenuId={0})", excludeSubmenus[i]); 

    if(i != excludeSubmenus.Count-1) 
     notExpr += " and "; 
    } 

XmlNodeList nextLevelNodeList = 
    currentNode.SelectNodes(
     string.Format("//Menu[MenuId in excludeSubMenus]/Item 
           [ItemLevel={1} and not(ItemType='Javascript')]", 
         notExpr, iLevel) 
        ); 

ध्यान दें करो: उपरोक्त कोड में तार विभिन्न भागों में विभाजित किया गया है पठनीयता बढ़ाने के लिए लाइनें। Ypur कोड में आपको किसी भी स्ट्रिंग को विभाजित नहीं करना चाहिए, या उसी प्रभाव को प्राप्त करने के लिए स्ट्रिंग + (concatenation) ऑपरेटर का उपयोग नहीं करना चाहिए।

+3

मैं एक स्ट्रिंगबिल्डर और AppendFormat का उपयोग करने की भी सिफारिश करता हूं। – Foole

+0

ठीक है, मैं वास्तव में देख रहा हूं कि आप क्या कर रहे हैं, सरणी के माध्यम से पुनरावृत्ति करते हैं और उस डेटा का उपयोग नोडलिस्ट में उपयोग की जाने वाली स्ट्रिंग बनाने के लिए करते हैं। मुझे गणना का उपयोग करते समय एक कंपाइलर त्रुटि मिल रही है - इसके बजाय लंबाई का उपयोग करने के लिए बदलने की कोशिश की, कोई त्रुटि नहीं, लेकिन कोई आउटपुट नहीं। कोई विचार? – Nathan

+0

@ नाथन: हाँ, यह 'लंबाई' है। "आउटपुट" के लिए, क्या आप कृपया अंतिम निर्मित XPath अभिव्यक्ति प्रिंट कर सकते हैं और इसे प्रदान कर सकते हैं, ताकि हम देख सकें कि क्या हो रहा है? –

0

मुझे 100% यकीन नहीं है कि आप यहां कौन से नोड्स की अपेक्षा करते हैं लेकिन जो आपने लिखने की कोशिश की है, उसके आधार पर, मैंने एक स्केलेबल तरीके से दोहराने की कोशिश की।

असल में आपको सही XPath बनाने के लिए सरणी की सामग्री का उपयोग करना होगा। यहां मेरे पास कुछ बहिष्करण सूचियों को उपयुक्त XPath स्थिति में बदलने में मदद करने के लिए कुछ फ़ंक्शन हैं। निजी तौर पर, मुझे लिखने और प्रबंधित करने के लिए यह बहुत आसान करने के लिए LINQ और string.Join() का उपयोग करना पड़ता है।

// supporting methods to build parts of the string 
static string ElementNotInList<T>(string element, params T[] list) 
{ 
    return String.Join(" and ", list.Select(x => String.Concat(element, "!=", x))); 
} 
static string ElementInList<T>(string element, params T[] list) 
{ 
    return String.Join(" or ", list.Select(x => String.Concat(element, "=", x))); 
} 


var excludeSubmenus = new[] { 2905, 323 }; 
var xpath = String.Join("|", 
    String.Format("//Menu[{0}]/Item[ItemLevel={1} and ItemType!='Javascript']", 
     ElementNotInList("MenuId", excludeSubmenus), iLevel), 
    String.Format("//Menu[{0}]/Item[ItemLevel={1} and ItemType='content']", 
     ElementInList("MenuId", excludeSubmenus), iLevel) 
); 
var nextLevelNodeList = currentNode.SelectNodes(xpath); 
0

याद रखें कि आप हमेशा क्रम में परीक्षण अस्तित्व के लिए XPath 1.0 अभिव्यक्ति इस तरह का उपयोग कर सकते हैं:

Menu/Item[ 
    contains(
     concat(' ','2905 323',' '), 
     concat(' ',../MenuId,' ') 
    ) and 
    ItemType = 'content' 
    or 
    ItemType != 'Javascript' 
][ 
    ItemLevel = {0} 
] 
0

धन्यवाद सभी सलाह के लिए - मैं अब के लिए एक सरल xpath एक्सप्रेशन के रूप में यह जा रहा हूँ , करने के लिए और अधिक महत्वपूर्ण चीजें हैं। चाहने की संभावना को बाहर करने के लिए और अधिक सबमेनू यथोचित स्लिम रहे हैं, और मैं उनके साथ सौदा करेंगे के रूप में वे उत्पन्न होती हैं ...

मैं नीचे का उपयोग कर रहा मेरी समाधान के रूप में -

 XmlNodeList nextLevelNodeList = currentNode.SelectNodes(string.Format("Menu[not(MenuId = 2905) and not(MenuId = 323)]/Item[ItemLevel={0} and ItemType != 'Javascript'] | Menu[MenuId = 2905 or MenuId = 323]/Item[ItemLevel={0} and ItemType='content']", iLevel)); 

यह एक सुंदर साधारण है शुरू करने के लिए एक्सएमएल दस्तावेज़, 12.5 एमबी वजन, और ईमानदार होने के लिए, मैं साइट के अन्य क्षेत्रों पर काम करना चाहूंगा ....

0

सबसे पहले, आपको "इन" अभिव्यक्ति की आवश्यकता नहीं है। = ऑपरेटर का स्वचालित रूप से अर्थ है "अगर यह अनुक्रम में कुछ भी मेल खाता है।"

आपके वास्तविक प्रश्न के लिए, यदि xpath अभिव्यक्ति को किसी प्रकार की वस्तु और बाध्य चर के रूप में सुधारना संभव है, तो यह संभवतः करना आसान है।मैं C++ partiucular में से परिचित नहीं हूँ, लेकिन मैं एक एसक्यूएल तैयार बयान में वैरिएबल का उपयोग कर की तरह थोड़ा

 
XPathExpr foo = XPathExpr("/Item[not(type=$badType)]");` 
foo.bind("badType", toXpathSquence(the_bad_types));` 
foo.eval(the_xml_to_evaluate);` 

की तरह कुछ देखने के लिए बहुत ज्यादा उम्मीद थी।

संबंधित मुद्दे