我有大量具有以下结构的XML文件:
<Stuff1>
<Content>someContent</name>
<type>someType</type>
</Stuff1>
<Stuff2>
<Content>someContent</name>
<type>someType</type>
</Stuff2>
<Stuff3>
<Content>someContent</name>
<type>someType</type>
</Stuff3>
...
...
我需要将每个“Content”节点名称更改为StuffxContent;基本上将父节点名称添加到内容节点的名称。
我计划使用XMLDocument
课程并找出方法,但我想我会问是否有更好的方法可以做到这一点。
答案 0 :(得分:53)
(1。)[XmlElement / XmlNode] .Name属性是只读的。
(2。)问题中使用的XML结构很粗糙,可以改进。
(3。)无论如何,这是给定问题的代码解决方案:
String sampleXml =
"<doc>"+
"<Stuff1>"+
"<Content>someContent</Content>"+
"<type>someType</type>"+
"</Stuff1>"+
"<Stuff2>"+
"<Content>someContent</Content>"+
"<type>someType</type>"+
"</Stuff2>"+
"<Stuff3>"+
"<Content>someContent</Content>"+
"<type>someType</type>"+
"</Stuff3>"+
"</doc>";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(sampleXml);
XmlNodeList stuffNodeList = xmlDoc.SelectNodes("//*[starts-with(name(), 'Stuff')]");
foreach (XmlNode stuffNode in stuffNodeList)
{
// get existing 'Content' node
XmlNode contentNode = stuffNode.SelectSingleNode("Content");
// create new (renamed) Content node
XmlNode newNode = xmlDoc.CreateElement(contentNode.Name + stuffNode.Name);
// [if needed] copy existing Content children
//newNode.InnerXml = stuffNode.InnerXml;
// replace existing Content node with newly renamed Content node
stuffNode.InsertBefore(newNode, contentNode);
stuffNode.RemoveChild(contentNode);
}
//xmlDoc.Save
PS:我来到这里寻找一种更好的方式来重命名节点/元素;我还在寻找。
答案 1 :(得分:3)
我发现重命名节点的最简单方法是:
xmlNode.InnerXmL = newNode.InnerXml.Replace("OldName>", "NewName>")
不要包含开头<
,以确保重命名结束</OldName>
标记。
答案 2 :(得分:0)
也许更好的解决方案是遍历每个节点,并将信息写入新文档。显然,这将取决于您将来如何使用这些数据,但我建议使用与FlySwat建议相同的重新格式化...
<stuff id="1">
<content/>
</stuff>
我还建议使用最近添加的XDocument是创建新文档的最佳方式。
答案 3 :(得分:0)
我会回答更高的问题:为什么要使用XmlDocument
尝试此操作?
我认为实现目标的最佳方法是使用简单的XSLT文件 匹配“CONTENTSTUFF”节点并输出“CONTENT”节点......
没有理由得到这么重的枪......
无论哪种方式,如果你仍然希望这样做C#Style,
出于内存和速度的目的,请使用XmlReader
+ XmlWriter
而非XmlDocument
。
XmlDocument
将整个XML存储在内存中,并使其在Traversing中非常繁重......
如果你多次访问该元素,XmlDocument很好(不是这里的情况)。
答案 4 :(得分:0)
我使用此方法来重命名节点:
/// <summary>
/// Rename Node
/// </summary>
/// <param name="parentnode"></param>
/// <param name="oldname"></param>
/// <param name="newname"></param>
private static void RenameNode(XmlNode parentnode, string oldChildName, string newChildName)
{
var newnode = parentnode.OwnerDocument.CreateNode(XmlNodeType.Element, newChildName, "");
var oldNode = parentnode.SelectSingleNode(oldChildName);
foreach (XmlAttribute att in oldNode.Attributes)
newnode.Attributes.Append(att);
foreach (XmlNode child in oldNode.ChildNodes)
newnode.AppendChild(child);
parentnode.ReplaceChild(newnode, oldNode);
}
答案 5 :(得分:0)
我不是XML方面的专家,就我而言,我只需要将HTML文件中的所有标签名都设为大写,以便在XmlDocument中使用GetElementsByTagName进行进一步操作。我需要大写的原因是,对于XmlDocument,标记名称区分大小写(因为它是XML),并且我不能保证标记名称中HTML文件的大小写一致。
所以我这样解决了它:我使用XDocument作为中间步骤,您可以在其中重命名元素(即标记名),然后将其加载到XmlDocument中。这是我的VB.NET代码(C#编码将非常相似)。
Dim x As XDocument = XDocument.Load("myFile.html")
For Each element In x.Descendants()
element.Name = element.Name.LocalName.ToUpper()
Next
Dim x2 As XmlDocument = New XmlDocument()
x2.LoadXml(x.ToString())
就我的目的而言,它工作得很好,尽管我知道在某些情况下,如果要处理纯XML文件,这可能不是解决方案。
答案 6 :(得分:-1)
将其作为字符串加载并在整个批次上进行替换..
String sampleXml =
"<doc>"+
"<Stuff1>"+
"<Content>someContent</Content>"+
"<type>someType</type>"+
"</Stuff1>"+
"<Stuff2>"+
"<Content>someContent</Content>"+
"<type>someType</type>"+
"</Stuff2>"+
"<Stuff3>"+
"<Content>someContent</Content>"+
"<type>someType</type>"+
"</Stuff3>"+
"</doc>";
sampleXml = sampleXml.Replace("Content","StuffxContent")
答案 7 :(得分:-28)
您提供的XML表明某人完全忽视了XML。
而不是
<stuff1>
<content/>
</stuff1>
你应该:/
<stuff id="1">
<content/>
</stuff>
现在您可以使用Xpath遍历文档(即// stuff [id ='1'] / content /)节点的名称不应该用于建立标识,您可以使用属性。< / p>
要执行您的要求,请将XML加载到xml文档中,然后简单地遍历重命名它们的第一级子节点。
伪代码:
foreach (XmlNode n in YourDoc.ChildNodes)
{
n.ChildNode[0].Name = n.Name + n.ChildNode[0].Name;
}
YourDoc.Save();
但是,我强烈建议您实际修复XML以使其有用,而不是进一步破坏它。