C# 如何在string.Format中引用数组值?

C# 如何在string.Format中引用数组值?,c#,.net,xml,xslt,xpath,C#,.net,Xml,Xslt,Xpath,我使用XPath排除菜单中的某些节点。我想对此进行扩展,以排除数组中标识的节点 此操作用于排除id为2905的菜单中类型为“非内容”的所有节点: XmlNodeList nextLevelNodeList = currentNode .SelectNodes(string .Format("

我使用XPath排除菜单中的某些节点。我想对此进行扩展,以排除数组中标识的节点

此操作用于排除id为2905的菜单中类型为“非内容”的所有节点:

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和其他几个存储在一个数组中,然后在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));
任何建议都将不胜感激

助教 内森

编辑-包含示例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>

322
子菜单
2.
322
2.
2905
子菜单
3.
2905
3.
19196
内容
4.
19192
子菜单
4.
2906
子菜单
3.
323
3.
2432
内容
4.
12353
子菜单
4.
使用

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)
                     ); 
int[]排除子菜单={2905323};
string notExpr=string.Empty;
for(int i=0;i

注意事项:在上述代码中,字符串被分成不同的行,以增强可读性。在ypur代码中,您不能拆分任何字符串,也不能使用字符串
+
(串联)运算符来实现相同的效果。

我不能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);
//支持构建字符串部分的方法
静态字符串元素NotInList(字符串元素,参数T[]列表)
{
返回String.Join(“and”,list.Select(x=>String.Concat(元素“!=”,x));
}
静态字符串元素列表(字符串元素,参数T[]列表)
{
返回String.Join(“or”,list.Select(x=>String.Concat(元素“=”,x));
}
var excludeSubmenus=new[]{2905323};
var xpath=String.Join(“|”,
String.Format(“//Menu[{0}]/Item[ItemLevel={1}和ItemType!='Javascript']”,
ElementNotInList(“MenuId”,不包括子菜单),iLevel),
String.Format(“//菜单[{0}]/Item[ItemLevel={1}和ItemType='content']”,
ElementInList(“MenuId”,不包括子菜单),iLevel)
);
var nextLevelNodeList=currentNode.SelectNodes(xpath);

请记住,始终可以使用这种XPath 1.0表达式按顺序测试存在性:

Menu/Item[
   contains(
      concat(' ','2905 323',' '),
      concat(' ',../MenuId,' ')
   ) and
   ItemType = 'content'
     or
   ItemType != 'Javascript'
][
   ItemLevel = {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));
首先,它是一个非常普通的xml文档,重量为12.5MB,老实说,我更愿意在站点的其他区域工作……

首先,您不需要“in”表达式。=运算符自动表示“如果它与序列中的任何内容匹配。”

至于您真正的问题,如果可以将xpath表达式具体化为某种对象和绑定变量,那么这可能很容易做到。我不熟悉C++中的部分,但我希望能看到一些类似

的东西。 XPathExpr foo = XPathExpr("/Item[not(type=$badType)]");` foo.bind("badType", toXpathSquence(the_bad_types));` foo.eval(the_xml_to_evaluate);` XPathExpr foo=XPathExpr(“/Item[not(type=$badType)]”` foo.bind(“badType”,toXpathSquence(坏类型))` eval(xml到evaluate)`
非常类似于在sql语句中使用变量。

好问题,+1。请参阅我的答案,以获得完整且简单的解决方案。:)请检查我的答案,了解一个经典的“顺序中存在”XPath 1.0表达式。我建议还使用StringBuilder和AppendFormat。好的,我完全了解您正在做什么,遍历数组并使用该数据创建节点列表中使用的字符串。我在使用Count时遇到了一个编译器错误-尝试将其改为使用Length,没有错误,但没有输出。有什么想法吗?@Nathan:是的,它是
Length
。至于“无输出”,请打印并提供最终构造的XPath表达式,以便我们看到发生了什么?@Nathan:还需要一个小样本XML文档。@dimitre-我在我的原始帖子中添加了一个XML样本。