使用LINQ将元素更新为XML? [英] Update elements using LINQ to XML?
问题描述
我有以下XML,但是我很难弄清楚如何使用LINQ to XML直接更新元素:
I have the following XML, but I am having a hard time figuring out how to update the elements directly using LINQ to XML:
XElement settings = XElement.Parse (
@"<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:wsa='http://schemas.xmlsoap.org/ws/2004/08/addressing'
xmlns:wsse='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'>
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand='1'>
<wsse:UsernameToken wsu:Id='UsernameToken-72135529'>
<wsse:Username>{USERNAME}</wsse:Username>
<wsse:Password Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'>{PASSWORD}</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
<wsa:MessageID>{MESSAGEID}</wsa:MessageID>
<wsa:To>{TO}</wsa:To>
<wsa:Action>{ACTION}</wsa:Action>
<wsa:From>
<wsa:Address>{ADDRESS}</wsa:Address>
</wsa:From>
</soapenv:Header>
<soapenv:Body>
{BODY}
</soapenv:Body>
</soapenv:Envelope>");
例如,在上面,我要访问每个具有placholder值{}
的元素并更新文本.在这种情况下,XElement.Parse()
是否正确?我最有可能先将其加载到XDocument
中,然后再更新元素.另外,如何更新属性,例如Password
上的Type属性?
For example, in the above, I want to access each element that has placholder value {}
and update the text. Is doing XElement.Parse()
correct in this scenario? I am most likely going to load it into and XDocument
first and then update the elements. Also, how could I update attributes, like the Type attribute on Password
?
试图获取用户名,但它说这是一个InvalidOperationException.
Trying to get to Username, but it says it is an InvalidOperationException.
XNamespace xmlns = "http://schemas.xmlsoap.org/soap/envelope/";
XNamespace wsa = "http://schemas.xmlsoap.org/ws/2004/08/addressing";
XNamespace wsse = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
XNamespace wsu = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
var textElement = settings.Elements(xmlns + "Envelope").
Elements(xmlns + "Header").
Elements(wsse + "Security").
Elements(wsse + "UsernameToken").
Elements(wsse + "Username").Single();
还是我吗?如果我知道元素的确切位置,并且例如想更新或删除xmlns:wsa,使用XPath看起来是否更简单?
Also, is it just me or does using XPath seem simpler if I know the exact position of the elements and if I wanted to update or remove xmlns:wsa for example, how would that be achieved?
推荐答案
可以做到
var elements = settings.DescendantNodes().OfType<XText>().Where(p => p.Value.StartsWith("{") && p.Value.EndsWith("}"));
foreach (var node in elements)
{
// This is an example of manipulation. It will simply remove the {}
node.Value = node.Value.Substring(1, node.Value.Length - 2);
}
您可以直接在for循环中移动Where
条件,例如
You could move the Where
condition directly in the for cycle, like
var elements = settings.DescendantNodes().OfType<XText>();
foreach (var node in elements.Where(p => p.Value.StartsWith("{") && p.Value.EndsWith("}")))
{
// This is an example of manipulation. It will simply remove the {}
node.Value = node.Value.Substring(1, node.Value.Length - 2);
}
查找XText
节点的说明来自 C#中的XElement值
请注意,您需要添加缺少的名称空间:
Note that you'll need to add the missing namespaces:
xmlns:wsse='something' xmlns:wsa='somethingelse' xmlns:wsu='somethingelseelse'
或XElement.Parse
会断开;
如果您要更新一个名称已知的元素:
If you want to update a single element of which you know the name:
XNamespace wsa = "somethingelse"; // Here you must put the namespace!
var textElement = settings.Descendants(wsa + "MessageID").Single(); // If there is only one Message ID to change (0 or > 1 MessageID will make Single throw), .First() if you are only interested in the first one
textElement.Value = "MessageID"; // Changed!
或
var textElements = settings.Descendants(wsa + "MessageID") // If there are multipleMessage ID to change
foreach (var textElement in textElements)
{
textElement.Value = "MessageID"; // Changed!
}
请注意,这些变体将更改第一个/所有wsa:MessageID,而忽略其位置.
Be aware that these variants will change the first/all the wsa:MessageID, ignoring their position.
或者如果您知道节点的确切路径",请使用
or if you know the exact "path" to your node, use something like
var textElements = settings.Elements(name1).Elements(name2)...
,然后使用Single()
,.First()
或foreach
一小段示例代码:
XElement settings = XElement.Parse(
@"<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:wsa='http://schemas.xmlsoap.org/ws/2004/08/addressing' xmlns:wsse='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'>
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand='1'>
<wsse:UsernameToken wsu:Id='UsernameToken-72135529'>
<wsse:Username>{USERNAME}</wsse:Username>
<wsse:Password Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'>{PASSWORD}</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
<wsa:MessageID>{MESSAGEID}</wsa:MessageID>
<wsa:To>{TO}</wsa:To>
<wsa:Action>{ACTION}</wsa:Action>
<wsa:From>
<wsa:Address>{ADDRESS}</wsa:Address>
</wsa:From>
</soapenv:Header>
<soapenv:Body>
{BODY}
</soapenv:Body>
</soapenv:Envelope>");
var soapenv = settings.GetNamespaceOfPrefix("soapenv");
var wsa = settings.GetNamespaceOfPrefix("wsa");
var wsse = settings.GetNamespaceOfPrefix("wsse");
var wsu = settings.GetNamespaceOfPrefix("wsu");
XElement username = settings.Elements(soapenv + "Header").Elements(wsse + "Security").Elements(wsse + "UsernameToken").Elements(wsse + "Username").Single();
Console.WriteLine(username);
username.Value = "NewValue";
Console.WriteLine(username);
这篇关于使用LINQ将元素更新为XML?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!