Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Winapi 使用XPath查询节点时如何指定命名空间? 短版_Winapi_Com_Msxml_Msxml6 - Fatal编程技术网

Winapi 使用XPath查询节点时如何指定命名空间? 短版

Winapi 使用XPath查询节点时如何指定命名空间? 短版,winapi,com,msxml,msxml6,Winapi,Com,Msxml,Msxml6,您可以通过以下方式在.NET中执行此操作: XmlNode.SelectNodes(query, selectionNamespaces); 你能用javascript做吗 你能用msxml做吗 尝试一个: 尝试B: 尝试C: 长版本 给定一个包含xml片段的 <row> <cell>a</cell> <cell>b</cell> <cell>c</cell> </row>

您可以通过以下方式在.NET中执行此操作:

XmlNode.SelectNodes(query, selectionNamespaces);
你能用javascript做吗

你能用msxml做吗

尝试一个:

尝试B:

尝试C:

长版本 给定一个包含xml片段的

<row>
    <cell>a</cell>
    <cell>b</cell>
    <cell>c</cell>
</row>
这将返回一个IXMLDOMNodeList:

A. B C 那很好

但是名称空间打破了它 如果XML片段来自具有命名空间的文档,例如:

<row xmlns:ss="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
    <cell>a</cell>
    <cell>b</cell>
    <cell>c</cell>
</row>
你得到你的手机:

A. B C 但这对节点不起作用 IXMLDOMNode具有

选择节点法

将指定的模式匹配操作应用于此节点的上下文,并将匹配节点的列表作为IXMLDOMNodeList返回

评论

有关在名称空间中使用selectNodes方法的更多信息,请参阅主题

但在对DOM节点发出XPath查询时,无法指定选择名称空间

使用XPath查询节点时,如何指定名称空间

.NET解决方案 .NET的XmlNode提供了一个SelectNodes方法,该方法提供并接受XmlNamespaceManager参数:

XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("peanut", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
cells = row.SelectNodes("/peanut:row/peanut:cell", ns);
但我不是C语言,也不是Javascript语言。本机的msxml6等价物是什么

编辑:我不太喜欢Javascript

完全极小示例
这在MSDN上得到了回答:

更新:

但是,请注意,在第二个示例XML中,将xmlns:peant添加到SelectionNamespaces属性时,XPath查询的命名空间中不包含和元素。这就是为什么找不到元素的原因

要将它们正确地放入命名空间,您必须:

将名称空间声明更改为使用xmlns=而不是xmlns:ss=:

A. B C 使用and代替and:

A. B C SelectionNamespaces属性不会神奇地将元素放入命名空间中,它只指定哪些命名空间可供XPath查询使用。XML本身必须根据需要将元素放入适当的名称空间

更新:

在您的新示例中,cells:=row.selectNodes'/ss:row/ss:cell';不起作用,因为XPath查询使用的是绝对路径,其中前导/起始于文档根,并且XML文档顶部没有元素,只有一个元素。这就是为什么行:=doc.selectNodes'/ss:worksheet/ss:row';工作

如果要执行从被查询节点开始的XPath查询,请不要使用绝对路径,而是使用相对路径:

cells := row.selectNodes('ss:row/ss:cell');
或者简单地说:

cells := row.selectNodes('ss:cell');

node.ownerDocument.setPropertySelectionNamespaces…@Ben这是个好主意。不幸的是,它根本不起作用——它根本不返回任何节点。你有JSFIDLE吗?@Ben我没有使用javascript,我使用的是原生Win32 COM msxml。你有JSFIDLE吗?我没有,但应该可以用JScript/Windows脚本主机重现这个问题?据我所知,代码调用Document.setProperty。i、 它查询的是一个文档而不是一个节点,因为它是整个DOM文档的属性,而不是单个节点的属性。运行XPath查询时,无论在哪个节点上运行查询,它都将使用文档的current SelectedNamespaces属性解析查询中的命名空间;它根本不起作用。本已经提出了上述建议。@IanBoyd它确实有效,我以前用过。您注意到我在回答中添加的额外信息了吗?您说添加SelectionNamespaces属性并不会神奇地将元素放入名称空间中。为什么当我添加SelectionNamespace时,它会神奇地将元素放入适合我的命名空间中?在问题中添加了完整的最小示例。
<row xmlns:ss="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
    <cell>a</cell>
    <cell>b</cell>
    <cell>c</cell>
</row>
IXMLDOMDocument3 doc = //...document xml above
doc.setProperty("SelectionNamespaces", "xmlns:peanut="http://schemas.openxmlformats.org/spreadsheetml/2006/main");

IXMLDOMNodeList cells = doc.selectNodes("/peanut:row/peanut:cell");
HRESULT selectNodes(  
      BSTR expression,  
      IXMLDOMNodeList **resultList); 
XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("peanut", "http://schemas.openxmlformats.org/spreadsheetml/2006/main");
cells = row.SelectNodes("/peanut:row/peanut:cell", ns);
program Project3;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, msxml, ActiveX;

procedure Main;
var
    s: string;
    doc: DOMDocument60;
    rows: IXMLDOMNodeList;
    row: IXMLDOMElement;
    cells: IXMLDOMNodeList;
begin
    s :=
            '<?xml version="1.0" encoding="UTF-16" standalone="yes"?>'+#13#10+
            '<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">'+#13#10+
            '<row>'+#13#10+
            '    <cell>a</cell>'+#13#10+
            '    <cell>b</cell>'+#13#10+
            '    <cell>c</cell>'+#13#10+
            '</row>'+#13#10+
            '</worksheet>';

    doc := CoDOMDocument60.Create;
    doc.loadXML(s);
    if doc.parseError.errorCode <> 0 then
        raise Exception.CreateFmt('Parse error: %s', [doc.parseError.reason]);

    doc.setProperty('SelectionNamespaces', 'xmlns:ss="http://schemas.openxmlformats.org/spreadsheetml/2006/main"');

    //Query for all the rows
    rows := doc.selectNodes('/ss:worksheet/ss:row');
    if rows.length = 0 then
        raise Exception.Create('Could not find any rows');

    //Do stuff with the first row
    row := rows[0] as IXMLDOMElement;

    //Get the cells in the row
    (row.ownerDocument as IXMLDOMDocument3).setProperty('SelectionNamespaces', 'xmlns:ss="http://schemas.openxmlformats.org/spreadsheetml/2006/main"');
    cells := row.selectNodes('/ss:row/ss:cell');
    if cells.length <> 3 then
        raise Exception.CreateFmt('Did not find 3 cells in the first row (%d)', [cells.length]);
end;

begin
  try
        CoInitialize(nil);
        Main;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
cells := row.selectNodes('ss:row/ss:cell');
cells := row.selectNodes('ss:cell');