我无法在 C#.Net 中的 SOAP 标头中正确选择 XML 节点



我有一个用SOAP头包装的XML文档,但我不能选择一个节点。我想我只是误解了当节点准备好文本时如何重新发送树。例如wsu:时间戳,wsu:创建

这是我的XML的顶部:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:itk="urn:nhs-itk:ns:201005">
    <soap:Header>
        <wsa:MessageID>39c6f52b-1be0-42a9-a219-5d6ececd1695</wsa:MessageID>
        <wsa:Action>urn:nhs-itk:services:201005:SendCDADocument-v2-0</wsa:Action>
        <wsa:To>http://127.0.0.1:4000/syncsoap</wsa:To>
        <wsa:From>
            <wsa:Address>http://localhost</wsa:Address>
        </wsa:From>
        <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="D6CD5232-14CF-11DF-9423-1F9A910D4703">
                <wsu:Created>2015-01-30T19:40:00</wsu:Created>
                <wsu:Expires>2015-01-30T19:50:00</wsu:Expires>
            </wsu:Timestamp>
            <wsse:UsernameToken>
                <wsse:Username>TKS Server test</wsse:Username>
            </wsse:UsernameToken>
        </wsse:Security>
    </soap:Header>

这是我的代码,它在SelectSingleNode上抛出一个空指针异常,因为它没有返回匹配项。

private static XmlDocument CreateSoapEnvelope()
{
    XmlDocument soapEnvelop = new XmlDocument();
    DateTime myCreatedDate = DateTime.UtcNow;

    soapEnvelop.Load(@“c:myFile.xml");
    soapEnvelop.SelectSingleNode("/soap/Envelope/Header/wsse/Security/wsu/Timestamp/Created").InnerText = myCreatedDate.ToString("yyyy-MM-ddTHH:mm:ssZ");
    return soapEnvelop;
}

我仔细检查了一下病例敏感性,没有发现任何错误。当我在中放置断点时,我可以看到XML被加载到soapEnvelop对象中。

我实现了使用命名空间管理器的建议,可以很好地选择几个节点。但是,我在匹配wsu:Timestamp中的Id值时遇到了问题。我尝试了以下操作,但都无法匹配:

soapEnvelop.SelectSingleNode("//soap:Envelope/soap:Header/wsse:Security/wsu:Timestamp/Id", ns).InnerText = Guid.NewGuid().ToString();
soapEnvelop.SelectSingleNode("//soap:Envelope/soap:Header/wsse:Security/wsu:Timestamp/wsu:Id", ns).InnerText = Guid.NewGuid().ToString();
soapEnvelop.SelectSingleNode("//soap:Envelope/soap:Header/wsse:Security/wsu:Timestamp", ns).Attributes["Id"].Value = Guid.NewGuid().ToString();

我解决了最后一个问题。如果有一个属性为空,则Value()调用必须"失败"。当我添加下面建议的代码时,我已经修改了我正在使用的xml文档,并删除了现有的ID并将其替换为",这就是我使用Created和Expires所做的。问题一定是,你可以为一个空字符串的节点设置InnerText,但不能为一个属性设置。也许这被认为是无效的XML,所以.Net说"不行,伙计"。

奇怪的是,当我在初始设置Id.之前更改代码进行此调用时

XmlNode myNode = soapEnvelop.SelectSingleNode("//soap:Envelope/soap:Header/wsse:Security/wsu:Timestamp", ns);
myNode.Attributes["wsu:Id"].Value = Guid.NewGuid().ToString();

即使在我的xml文件中Id为",它也会对该值进行微调。这就是我偶然发现我的解决方案的原因,因为我把原来的调用留在了代码中,它没有抛出异常,所以它让我认为唯一的区别是Id有一个值。

谢谢,Dan

这是一个命名空间问题。您选择的节点并不都属于同一个命名空间,因此实际上无法访问它们。您需要使用XmlNameSpaceManager来存储命名空间,并指定每个元素属于哪个命名空间。

例如:

    private static XmlDocument CreateSoapEnvelope()
    {
        XmlDocument soapEnvelop = new XmlDocument();
        DateTime myCreatedDate = DateTime.UtcNow;

        soapEnvelop.Load(@"c:myFile.xml");
        XmlNamespaceManager ns = new XmlNamespaceManager(soapEnvelop.NameTable);
        ns.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
        ns.AddNamespace("wsa", "http://www.w3.org/2005/08/addressing");
        ns.AddNamespace("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
        ns.AddNamespace("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
        soapEnvelop.SelectSingleNode("//soap:Envelope/soap:Header/wsse:Security/wsu:Timestamp/wsu:Created", ns).InnerText = myCreatedDate.ToString("yyyy-MM-ddTHH:mm:ssZ");
    }

有更优雅的方法来执行这项任务,但这至少会让你继续下去。

最新更新