linq-to-xml
2011-10-18 3 views 0 likes 
0

나는 다음과 같은 XML,하지만 내가 직접 XML에 LINQ를 사용하여 요소를 업데이트하는 방법을 알아내는 힘든 시간을 겪고 있습니다 위의 예를 들어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 속성과 같은 속성을 어떻게 업데이트 할 수 있습니까?

사용자 이름을 가져 오려고했지만 InvalidOperationException이라고합니다. WSA를 예를 들어, 어떻게 달성 할 것 : 또한

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(); 

, 내가 요소의 정확한 위치를 알고 있다면 그냥 날 또는 XPath를 사용하여 않고 간단 것 그리고 내가 업데이트하거나의 xmlns를 제거하고 싶다면 무엇입니까?

답변

1

이것은

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); 
} 

당신은 XText 노드를 찾는

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); 
} 

명령과 같은주기의에 직접 Where 조건을 움직일 수 할 것입니다 XElement value in C#

주 출신이 누락 된 네임 스페이스를 추가해야합니다.

xmlns:wsse='something' xmlns:wsa='somethingelse' xmlns:wsu='somethingelseelse' 

또는 XElement.Parse은 중단됩니다.

당신이 이름을 알고있는 하나의 요소 업데이트하려면 :

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를, 그들의 위치를 ​​무시.

하거나 Single().First() 또는 foreach

작은 샘플 코드를 사용하여 노드에 대한 정확한 "경로"를 알고 다음

var textElements = settings.Elements(name1).Elements(name2)... 

과 같은 것을 사용하는 경우 :

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); 
+0

디자인 타임에 자리 표시 자 요소를 알 수 있으므로 {USERNAME} 요소를 얻고 싶다면 어떻게해야합니까? {USERNAME}을 (를) 실제 값으로 바꿉니다. – Xaisoft

+0

예제를 – xanatos

+0

업데이트했습니다. 몇 가지 포인트가 있습니다. 이미 선언 된 네임 스페이스가 있습니다. 예를 들어 그 네임 스페이스를 생략 했으므로 wsa, wsu, wsse가 있습니다. 또한 요소의 정확한 배치를 알고 있습니다.왜 네임 스페이스를 선언해야하는지 궁금해서'settings.Elements ("Header") 요소 ("Security") 요소 ("UsernameToken") 요소 ("Username") .Single()',하지만 그것은 시퀀스에 요소가 없다고 말했습니다. – Xaisoft

0

또한 다음을 수행하여 네임 스페이스를 선언하지 않고도 로컬 이름을 사용할 수 있음을 알게되었습니다.

관련 문제