我应该使用什么命名空间来搜索此XML文档?

时间:2014-03-21 03:41:26

标签: xml xpath

我正在尝试找到节点" PermissionSet"在以下XML中。我对XPath不太熟悉,所以我试图走树去到我想要的节点。

我像这样加载XML:

var reader = new XmlTextReader(manifestFilename)
XNamespace _manifestNamespace = "urn:schemas-microsoft-com:asm.v1";
_appManifest = XElement.Load(reader);
var node1 = _appManifest.Elements(_manifestNamespace + "trustInfo").FirstOrDefault();
var node2 = node1.Elements(_manifestNamespace + "security").FirstOrDefault();
var node3 = node2.Elements(_manifestNamespace + "applicationRequestMinimum").FirstOrDefault();
var node4 = node3.Elements(_manifestNamespace + "PermissionSet").FirstOrDefault();

我的第一个节点一直空着。我怀疑我使用的命名空间是错误的,但我不知道该使用什么。这是XML:

<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app" />
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <!-- UAC Manifest Options
            If you want to change the Windows User Account Control level replace the 
            requestedExecutionLevel node with one of the following.

        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
        <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />

            Specifying requestedExecutionLevel node will disable file and registry virtualization.
            If you want to utilize File and Registry Virtualization for backward 
            compatibility then delete the requestedExecutionLevel node.
        -->
        <requestedExecutionLevel level="asInvoker" uiAccess="false" />
      </requestedPrivileges>
      <applicationRequestMinimum>
        <defaultAssemblyRequest permissionSetReference="Custom" />
        <PermissionSet class="System.Security.PermissionSet" version="1" ID="Custom" SameSite="site" />
      </applicationRequestMinimum>
    </security>
  </trustInfo>
</asmv1:assembly>

2 个答案:

答案 0 :(得分:0)

xmlns="urn:schemas-microsoft-com:asm.v2"

xmlns=属性声明了一个默认命名空间,它适用于从它出现的元素开始的所有非前缀元素,并“继承”到其所有后代,直到并且除非出现另一个xmlns=属性设置不同的默认值(或将默认值设置为no-namespace,如果值为"")。

请注意,默认命名空间仅适用于元素。除非属性名称包含名称空间前缀,否则属性永远不会被命名空间。

答案 1 :(得分:0)

您尝试选择的

<PermissionSet>元素驻留在此命名空间中:“urn:schemas-microsoft-com:asm.v2”。这是继承自它的祖先<trustInfo>元素:

<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    ........
        <PermissionSet class="System.Security.PermissionSet" version="1" ID="Custom" SameSite="site" />
    ........
</trustInfo>

所以你可以通过这种方式获得<PermissionSet>元素:

XNamespace v2 = "urn:schemas-microsoft-com:asm.v2";
var result = _appManifest.Root
                         .Element(v2 + "trustInfo")
                         .Element(v2 + "security")
                         .Element(v2 + "applicationRequestMinimum")
                         .Element(v2 + "PermissionSet");

更新:

你的评论是对的,如果缺少任何元素(除了最后一个元素,PermissionSet),我的代码将抛出空引用异常。但这不是这个答案的重点,只是为了简单起见。无论如何,更清洁的方法来避免这种异常恕我直言,正在使用XPath查询:

var nsManager = new XmlNamespaceManager(new NameTable());
nsManager.AddNamespace("v2", "urn:schemas-microsoft-com:asm.v2");
var result = _appManifest
                .Root
                .XPathSelectElement(
                    "./v2:trustInfo/v2:security/v2:applicationRequestMinimum/v2:PermissionSet"
                    , nsManager);

XPathSelectElement()更强大,可以处理不受控制的XML结构。无论丢失什么元素/属性,它都不会抛出异常。如果没有元素与XPath参数匹配,冷静地会返回null