修改xml节点的innertext和属性值

时间:2012-03-23 22:16:50

标签: c# xml recursion

我在获取所需输出时遇到了一些麻烦。我正在尝试解析XML并修改一些节点innertext和属性值。

我能够按照我的预期使属性部分工作,但不能获得节点的非文本值。

示例xml:

<?xml version="1.0" encoding="utf-8"?>
<hand:definitions xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:tns="http://joker.org/" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/hand/contract" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:soap="http://schemas.xmlsoap.org/hand/soap/" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsaw="http://www.w3.org/2006/05/addressing/hand" xmlns:soap12="http://schemas.xmlsoap.org/hand/soap12/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="projectAppSvc" targetNamespace="http://joker.org/" xmlns:hand="http://schemas.xmlsoap.org/hand/">
  <hand:service name="projectAppSvc">
    <hand:port name="BasicHttpBinding_IprojectAppSvc" binding="tns:BasicHttpBinding_IprojectAppSvc">
      <soap:address location="http://mywebsite:5255/projectappmgr/basic" />
    </hand:port>
    <hand:port name="WSHttpBinding_IprojectAppSvc" binding="tns:WSHttpBinding_IprojectAppSvc">
      <soap12:address location="http://mywebsite:5255/projectappmgr/ws" />
      <wsa10:Reference>
        <wsa10:Address>http://mywebsite:5255/projectappmgr/ws</wsa10:Address>
          <id xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingid">
            <Upn>number</Upn>
          </id>
       </wsa10:Reference>
     </hand:port>
   <hand:port name="NetTcpBinding_IprojectAppSvc" binding="tns:NetTcpBinding_IprojectAppSvc">
       <soap12:address location="net.tcp://mywebsite:5256/projectappmgr" />
       <wsa10:Reference>
          <wsa10:Address>net.tcp://mywebsite:5256/projectappmgr</wsa10:Address>
             <id xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingid">
                <Upn>number</Upn>
             </id>
          </wsa10:Reference>
       </hand:port>
 </hand:service>
</hand:definitions>

我有以下内容:

public static void ParseXML(XmlNode root)
{
    foreach (XmlNode node in root.ChildNodes)
    {
        XmlAttributeCollection attributes = node.Attributes;

        if (attributes != null)
            foreach (XmlAttribute attribute in attributes)
            {
                Console.WriteLine(attribute.Name + ": " + attribute.Value);
                if (attribute.Value.Contains("mywebsite"))
                {
                    Console.WriteLine("found an ATTRIBUTE value that contains localhost");
                    string origValue = attribute.Value;
                    string modValue = System.Text.RegularExpressions.Regex.Replace(origValue, "mywebsite(:\\d+){0,1}", "NEW_WEBSITE");
                    attribute.Value = modValue;
                }
                ParseXML(node);
            }
    }
}

这似乎工作正常并按我的预期修改xml,替换属性值包含“mywebsite”和“NEW_WEBSITE”:

<?xml version="1.0" encoding="utf-8"?>
<hand:definitions xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:tns="http://joker.org/" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/hand/contract" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:soap="http://schemas.xmlsoap.org/hand/soap/" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsaw="http://www.w3.org/2006/05/addressing/hand" xmlns:soap12="http://schemas.xmlsoap.org/hand/soap12/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="projectAppSvc" targetNamespace="http://joker.org/" xmlns:hand="http://schemas.xmlsoap.org/hand/">
  <hand:service name="projectAppSvc">
    <hand:port name="BasicHttpBinding_IprojectAppSvc" binding="tns:BasicHttpBinding_IprojectAppSvc">
      <soap:address location="http://NEW_WEBSITE/projectappmgr/basic" />
    </hand:port>
    <hand:port name="WSHttpBinding_IprojectAppSvc" binding="tns:WSHttpBinding_IprojectAppSvc">
      <soap12:address location="http://NEW_WEBSITE/projectappmgr/ws" />
      <wsa10:Reference>
        <wsa10:Address>http://mywebsite:5255/projectappmgr/ws</wsa10:Address>
          <id xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingid">
            <Upn>number</Upn>
          </id>
       </wsa10:Reference>
     </hand:port>
   <hand:port name="NetTcpBinding_IprojectAppSvc" binding="tns:NetTcpBinding_IprojectAppSvc">
       <soap12:address location="net.tcp://NEW_WEBSITE/projectappmgr" />
       <wsa10:Reference>
          <wsa10:Address>net.tcp://mywebsite:5256/projectappmgr</wsa10:Address>
             <id xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingid">
                <Upn>number</Upn>
             </id>
          </wsa10:Reference>
       </hand:port>
 </hand:service>
</hand:definitions>

我还要修改以下内容:

 <wsa10:Address>http://mywebsite:5255/projectappmgr/ws</wsa10:Address>

我在foreach循环中尝试了以下内容:

 if (node.InnerText.Contains("mywebsite"))
 {
     Console.WriteLine("found an NODE value that contains "mywebsite");
     string origValue1 = node.InnerText;
     string modValue1 = System.Text.RegularExpressions.Regex.Replace(origValue1,
                                                                 "mywebsite(:\\d+){0,1}",
                                                                             "NEW_WEBSITE");
     node.InnerText = modValue1;
 }

但这显然不正确,因为输出不是我想要的。

1 个答案:

答案 0 :(得分:1)

InnerText返回元素的整个文本内容 - 包括子元素中包含的文本,因此测试:

if (node.InnerText.Contains("mywebsite")) 

对于XML中的几乎所有元素都是如此,包括根元素,以及执行时

 node.InnerText = modValue1;   

你消灭了所有的子元素。

您必须明确地测试您要查找的元素:

 XmlElement element = node as XmlElement;
 if (element != null && 
     element.LocalName == "address" && 
     element.InnerText.Contains("mywebsite")) {

或者你应该测试节点是只有一个孩子(文本)的元素:

 XmlElement element = node as XmlElement;
 if (element != null && 
     element.InnerText.Contains("mywebsite") &&
     element.ChildNodes.Count == 1) {