2011-02-07 23 views
6

Tôi đang sử dụng XPath để loại trừ các nút nhất định trong một menu. Tôi muốn mở rộng trên điều này để loại trừ các nút được xác định trong một mảng.Làm cách nào để tham chiếu các giá trị mảng trong chuỗi.Format?

này hoạt động để loại trừ tất cả các nút trong menu với id 2905 có loại không phải là nội dung:

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

Những gì tôi muốn là để lưu trữ các menuId và một số người khác trong một mảng và sau đó tham khảo mà mảng bên trong hàm string.Format

Cái gì như:

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

Lời khuyên nào sẽ được đánh giá cao!

ta Nathan

Edit - bao gồm ví dụ xml

<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

Câu hỏi hay, +1. Xem câu trả lời của tôi cho một giải pháp hoàn chỉnh và dễ dàng. :) –

+0

Kiểm tra câu trả lời của tôi cho biểu thức XPath 1.0 "tồn tại theo thứ tự" cổ điển. –

Trả lời

1

Sử dụng:

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

Do lưu ý: Trong đoạn mã trên các dây đã được chia thành khác nhau để tăng cường khả năng đọc. Trong mã ypur, bạn không được phân chia bất kỳ chuỗi nào hoặc sử dụng toán tử chuỗi + (nối) để đạt được cùng một hiệu ứng.

+3

Tôi cũng khuyên bạn nên sử dụng một StringBuilder và AppendFormat. – Foole

+0

Ok, tôi thấy chính xác những gì bạn đang làm, lặp qua mảng và sử dụng dữ liệu đó để tạo chuỗi được sử dụng trong NodeList. Tôi nhận được một trình biên dịch errror khi sử dụng Count - cố gắng thay đổi đó để sử dụng chiều dài thay vào đó, không có lỗi nhưng không có đầu ra. Bất kỳ ý tưởng? – Nathan

+0

@Nathan: Vâng, đó là 'Length'. Đối với "không có đầu ra", bạn có thể, xin vui lòng, in các biểu thức XPath xây dựng cuối cùng và cung cấp nó, để chúng ta có thể xem những gì đang xảy ra? –

0

Tôi không chắc chắn 100% các nút bạn mong đợi ở đây nhưng dựa trên những gì bạn đã cố gắng viết, tôi đã cố gắng sao chép theo cách có thể mở rộng.

Về cơ bản bạn sẽ phải sử dụng nội dung của mảng để xây dựng đúng XPath. Ở đây tôi có một số chức năng để giúp thay đổi các danh sách loại trừ này thành điều kiện XPath thích hợp. Cá nhân, tôi tìm thấy bằng cách sử dụng LINQ và string.Join() để làm điều này dễ dàng hơn nhiều để viết và quản lý.

// 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

Hãy nhớ rằng bạn luôn có thể sử dụng loại XPath 1.0 biểu để thử nghiệm sự tồn tại trong chuỗi:

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

Cảm ơn tất cả những lời khuyên - Tôi đi đây nó như là một biểu thức XPath đơn giản cho bây giờ , có nhiều việc quan trọng hơn để làm. Cơ hội muốn loại trừ thêm các menu con là hợp lý mỏng, và tôi sẽ đối phó với họ khi họ xuất hiện ...

Tôi đang sử dụng dưới đây như là giải pháp của tôi -

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

Đó là một khá bình thường xml doc để bắt đầu với, nặng 12,5 mb, và thành thật mà nói, tôi muốn làm việc trên các khu vực khác của trang web ....

0

Thứ nhất, bạn không cần biểu thức "trong". Toán tử = tự động có nghĩa là "nếu nó khớp với bất kỳ thứ gì trong chuỗi."

Đối với câu hỏi thực sự của bạn, nếu có thể sửa đổi biểu thức xpath như một số loại đối tượng và biến liên kết, thì có thể dễ dàng thực hiện.Tôi không quen thuộc với C++ trong partiucular, nhưng tôi mong đợi để xem một cái gì đó mơ hồ như

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

rất giống như sử dụng các biến trong câu lệnh chuẩn bị sql.

Các vấn đề liên quan