C# 从具有xml结构的字符串中删除节点

C# 从具有xml结构的字符串中删除节点,c#,.net,xml,C#,.net,Xml,我有一个字符串参数,其中包含xml内容。基本上,字符串内部有一个XML string S = funcThatReturnsXML (parameters); S有下一个文本: <?xml version="1.0" encoding="utf-8" ?> <tagA> <tagB> <tagBB> .. . . </tagBB> . . </tagB> <tagC> .. .. . </t

我有一个字符串参数,其中包含xml内容。基本上,字符串内部有一个
XML

string S = funcThatReturnsXML (parameters);
S
有下一个文本:

<?xml version="1.0" encoding="utf-8" ?> 
<tagA>

<tagB> 

<tagBB>
..
.
.
</tagBB>
.
.
</tagB>

<tagC> 
..
..
.

</tagC>

</tagA>
如何从字符串
S
(非XML对象)的特定节点删除,例如

编辑:这是我测试的XML:

 <?xml version="1.0" ?> 
- <Request xmlns:xsi="http://www.mysite.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- <info xmlns="http://www.mysite.com">
  <RequestTR>54</RequestTR> 
  <time>2013-12-22</time> 
  </info>
- <Parameters xmlns="http://www.mysite.com">
  <id>3</id> 
  <name>2</name> 
  </Parameters>
  <title>Request</title> 
  </Request>

- 
- 
54
2013-12-22 
- 
3.
2.
要求

如果可以确定要从返回的XML中删除的特定外部元素,则可以使用LINQ to XML:

var returnedXml = funcThatReturnsXML(parameters);
var xmlElementToRemove = funcThatReturnsOuterElement(returnedXml);
var xelement = XElement.Load("XmlDoc.txt");
xelement.Elements().Where(e => e.Name == xmlElementToRemove).Remove();
例如:

using System.Linq;
using System.Xml.Linq;

class Program
{
    static void Main(string[] args)
    {
        // pretend this is the funThatReturnsXML return value
        var returnedXml = "<tagB><tagBB></tagBB></tagB>";
        // get the outer XML element name
        var xmlElementToRemove = GetOuterXmlElement(returnedXml);
        // load XML from where ever
        var xelement = XElement.Load("XmlDoc.txt");
        // remove the outer element and all subsequent elements
        xelement.Elements().Where(e => e.Name == xmlElementToRemove).Remove();
    }

    static string GetOuterXmlElement(string xml)
    {
        var index = xml.IndexOf('>');
        return xml.Substring(1, index - 1);
    }
}
使用System.Linq;
使用System.Xml.Linq;
班级计划
{
静态void Main(字符串[]参数)
{
//假设这是funThatReturnsXML返回值
var returnedXml=“”;
//获取外部XML元素名称
var xmlementtoremove=getouterxmlement(returnedXml);
//从何处加载XML
var-xelement=xelement.Load(“XmlDoc.txt”);
//拆下外部元件和所有后续元件
element.Elements().Where(e=>e.Name==xmlElementToRemove.Remove();
}
静态字符串GetOuterXmlElement(字符串xml)
{
var index=xml.IndexOf('>');
返回xml.Substring(1,索引-1);
}
}
请注意,以上是一种“贪婪”删除方法,如果有多个元素的名称通过
getouterxmlemet
方法返回,它们将全部删除。如果要删除某个特定实例,则需要更复杂的操作。

尝试以下操作:

string S = funcThatReturnsXML(parameters);
var doc = XDocument.Parse(S);
var nodeToRemove = doc.Descendants("tagB");
nodeToRemove.Remove();
这将从包含xml的字符串S中删除所有名为“tagB”的节点

更新1:

抱歉,我没有再添加一行:

S = doc.ToString();
我上面的第一个代码从doc中删除了“tagB”,但没有将其保存回S变量

更新2:

我使用以下包含属性的xml进行了测试:

<tagA attribute="value">
    <tagB> 
        <tagBB>
        </tagBB>
    </tagB>
    <tagC></tagC>
</tagA>
更新3:

鉴于您更新的xml格式,我知道为什么我以前的代码不适合您。这是因为您的xml已经声明了名称空间(xmlns)。解决方案是在搜索要删除的节点时使用LocalName,这将搜索节点名,同时忽略其名称空间。下面的示例显示如何删除所有“info”节点:

基于您的编辑:

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(S);

var nodeA = xmlDoc.SelectSingleNode("/tagA");
var nodeB = nodeA.SelectSingleNode("tagB");
nodeA.RemoveChild(nodeB);
要删除(可能)位于未知位置的多个
tagB
节点,您可以尝试:

var bees = xmlDoc.SelectNodes("//tagB");
foreach (XmlNode bee in bees) {
    var parent = bee.ParentNode;
    parent.RemoveChild(bee);
}

是否有一个特定的原因使您无法创建一个
XmlDocument
实例,调用
LoadXml()
,并处理它?我这样问是因为您编写了“非XML对象”。在返回XML(参数)的
函数中,它正在创建一个
XML对象
,但将其作为
字符串
xmlObject.InnerXml
返回。我无法更改此基本函数,因此我只想修复我正在使用的字符串。我建议您无论如何(重新)使用该字符串构建一个XmlDocument。尝试过它…使用
xmlDoc。选择SingleNode(“tagB”)返回NullXPath错误。。。请尝试
xmlDoc.SelectSingleNode(“/tagA/tagB”)
xmlDoc.SelectSingleNode(“/tagB”)
。感谢您的回答,问题是
每次都在不同的地方,我不能在不知道所有父节点的情况下找到它吗?“//tagB”是贪婪的xpath意思;把任何元素带到任何地方。因此,即使tagB嵌套在不同级别的多个元素中,它也能工作。@Dima请参阅我的更新。如果您检查了是否从S中删除,那么是的,它没有,但是通过添加
S=doc.ToString()它会删除结尾。@Dima我用一个包含属性的xml进行了测试,程序仍在运行。让我知道你的xml,如果它仍然不为你工作它仍然不工作,我把xml添加到我的question@Dima更新了我的答案。试试看,它对我有用。
var doc = XDocument.Parse(S);
var nodeToRemove = doc.Descendants().Where(o => o.Name.LocalName == "info");
nodeToRemove.Remove();
S = doc.ToString();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(S);

var nodeA = xmlDoc.SelectSingleNode("/tagA");
var nodeB = nodeA.SelectSingleNode("tagB");
nodeA.RemoveChild(nodeB);
var bees = xmlDoc.SelectNodes("//tagB");
foreach (XmlNode bee in bees) {
    var parent = bee.ParentNode;
    parent.RemoveChild(bee);
}