gpt4 book ai didi

c# - 删除没有子节点的父节点

转载 作者:数据小太阳 更新时间:2023-10-29 01:53:46 25 4
gpt4 key购买 nike

我有一个关于从 xml 文件中删除特定节点的问题。

这是我的 XML 示例:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<nodeA attribute="1">
<nodeB attribute="table">
<nodeC attribute="500"></nodeC>
<nodeC attribute="5"></nodeC>
</nodeB>
<nodeB attribute="3">
<nodeC attribute="4"></nodeC>
<nodeC attribute="5"></nodeC>
<nodeC attribute="5"></nodeC>
</nodeB>
<nodeB attribute="placeHolder">
<nodeB attribute="toRemove">
<nodeB attribute="glass"></nodeB>
<nodeE attribute="7"></nodeE>
<nodeB attribute="glass"></nodeB>
<nodeB attribute="glass"></nodeB>
</nodeB>
</nodeB>
<nodeB attribute="3">
<nodeC attribute="4"></nodeC>
<nodeC attribute="5"></nodeC>
<nodeC attribtue="5"></nodeC>
</nodeB>
<nodeB attribute="placeHolder">
<nodeB attribute="toRemove">
<nodeB attribute="glass"></nodeB>
<nodeE attribute="7"></nodeE>
<nodeB attribute="glass"></nodeB>
<nodeB attribute="glass"></nodeB>
</nodeB>
</nodeB>
</nodeA>
</root>

我想删除节点 nodeB="toRemove" 而不删除该节点的子节点。之后我需要对 nodeB attribute="placeHolder" 做同样的事情。部分结果如下所示:

     <nodeB attribute="3">
<nodeC attribute="4"></nodeC>
<nodeC attribute="5"></nodeC>
<nodeC attribtue="5"></nodeC>
</nodeB>
<nodeB attribute="glass"></nodeB>
<nodeE attribute="7"></nodeE>
<nodeB attribute="glass"></nodeB>
<nodeB attribute="glass"></nodeB>

我一直在尝试这样的代码来实现:

        XmlNodeList nodeList = doc.SelectNodes("//nodeB[@attribute=\"toRemove\"]");

foreach (XmlNode node in nodeList)
{
foreach (XmlNode child in node.ChildNodes)
{
node.ParentNode.AppendChild(child);
}
node.ParentNode.RemoveChild(node);
}
doc.Save(XmlFilePathSource);

我能够找到具有所需属性 toRemove 或 placeHolder 的节点,但是我无法将此节点的子节点向上移动一级。在这种情况下你能帮我吗?它可以是 Linq、XDocument、XmlReader 的解决方案,但我更喜欢使用 XmlDocument。感谢您提前为我提供的任何帮助。

编辑:

在这种情况下,我使用了 Chuck Savage 在下面写的稍微修改过的代码(以保持顺序)。一次删除

  <nodeB attribute="toRemove"> </nodeB>

然后对

做同样的事情
  <nodeB attribute="placeHolder"></nodeB>

这里是稍微修改过的代码

  XElement root = XElement.Load(XmlFilePathSource); 
var removes = root.XPathSelectElements("//nodeB[@attribute=\"toRemove\"]");
foreach (XElement node in removes.ToArray())
{
node.Parent.AddAfterSelf(node.Elements());
node.Remove();
}
root.Save(XmlFilePathSource);

@MiMo 提供的 xslt 方法在这种情况下也非常有用。

最佳答案

问题是您不能在枚举子节点时修改文档节点 - 您应该创建新节点而不是尝试修改现有节点,使用 XmlDocument 会变得有点棘手。 .

进行这种转换的最简单方法是使用 XSLT,即应用此 XSLT:

<xsl:stylesheet 
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" indent="yes"/>

<xsl:template match="nodeB[@attribute='toRemove' or @attribute='placeHolder']">
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="text()">
</xsl:template>

<xsl:template match="@* | *">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>

输入文件的输出是:

<root>
<nodeA attribute="1">
<nodeB attribute="table">
<nodeC attribute="500" />
<nodeC attribute="5" />
</nodeB>
<nodeB attribute="3">
<nodeC attribute="4" />
<nodeC attribute="5" />
<nodeC attribute="5" />
</nodeB>
<nodeB attribute="glass" />
<nodeE attribute="7" />
<nodeB attribute="glass" />
<nodeB attribute="glass" />
<nodeB attribute="3">
<nodeC attribute="4" />
<nodeC attribute="5" />
<nodeC attribtue="5" />
</nodeB>
<nodeB attribute="glass" />
<nodeE attribute="7" />
<nodeB attribute="glass" />
<nodeB attribute="glass" />
</nodeA>
</root>

应用 XSLT 的代码很简单:

  XslCompiledTransform transform = new XslCompiledTransform();
transform.Load(@"c:\temp\nodes.xslt");
transform.Transform(@"c:\temp\nodes.xml", @"c:\temp\nodes-cleaned.xml");

如果不可能(或不希望)为 XSLT 使用外部文件,则可以从字符串中读取它:

  string xsltString =
@"<xsl:stylesheet
version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>

<xsl:output method=""xml"" indent=""yes""/>

<xsl:template match=""nodeB[@attribute='toRemove' or @attribute='placeHolder']"">
<xsl:apply-templates/>
</xsl:template>

<xsl:template match=""text()"">
</xsl:template>

<xsl:template match=""@* | *"">
<xsl:copy>
<xsl:apply-templates select=""@* | node()""/>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>";
XslCompiledTransform transform = new XslCompiledTransform();
using (StringReader stringReader = new StringReader(xsltString))
using (XmlReader reader = XmlReader.Create(stringReader)) {
transform.Load(reader);
}
transform.Transform(@"c:\temp\nodes.xml", @"c:\temp\nodes-cleaned.xml");

关于c# - 删除没有子节点的父节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14967293/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com