C# XDocument保存删除节点前缀
我有一个XML文档(自制),其结构如下:C# XDocument保存删除节点前缀,c#,xml,linq-to-xml,C#,Xml,Linq To Xml,我有一个XML文档(自制),其结构如下: <?xml version="1.0" encoding="utf-8"?> <wf:wf version="1.0a" xmlns:wf="http://example.com/workflow" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://exa
<?xml version="1.0" encoding="utf-8"?>
<wf:wf version="1.0a" xmlns:wf="http://example.com/workflow" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://example.com/workflow">
<wf:assemblies />
<wf:dataDefinitions />
<wf:processes />
<wf:workflows>
<wf:workflow id="g08615517-cdfd-4091-a053-217a965f7118">
<wf:arguments />
<wf:variables>
<wf:variable id="g39ffecc9-f570-41c1-9ee0-b9358d63da3c" parameterType="Hidden">
<wf:name>UIPTaskId</wf:name>
<wf:dataDefinitionId>gc8f3715c-4a82-42d2-916c-51515083e7e5</wf:dataDefinitionId>
</wf:variable>
<wf:variable id="g46663a0c-7e60-4bd2-80df-16cd544087ad" parameterType="Hidden">
<wf:name>UIPTaskName</wf:name>
<wf:dataDefinitionId>g359FC555-9CC7-47D4-8ED3-EF973E7D74D7</wf:dataDefinitionId>
<wf:value>Responsible Individual</wf:value>
</wf:variable>
<wf:variable id="gb32914d5-6761-4e82-b571-c8944a796fd9" parameterType="Hidden">
<wf:name>Search?</wf:name>
<wf:dataDefinitionId>g57201da8-62b4-46f2-9329-c71d86f39ffc</wf:dataDefinitionId>
<wf:value>True</wf:value>
</wf:variable>
</wf:variables>
</wf:workflow>
</wf:workflows>
</wf:wf>
Save方法生成以下XML:
<?xml version="1.0" encoding="utf-8"?>
<wf version="1.0a" xmlns:wf="http://example.com/workflow" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://example.com/workflow">
<assemblies />
<dataDefinitions />
<processes />
<workflows>
<workflow id="g08615517-cdfd-4091-a053-217a965f7118">
<arguments />
<variables>
<variable id="g39ffecc9-f570-41c1-9ee0-b9358d63da3c" parameterType="Hidden">
<name>UIPTaskId</name>
<dataDefinitionId>gc8f3715c-4a82-42d2-916c-51515083e7e5</dataDefinitionId>
</variable>
<variable id="g46663a0c-7e60-4bd2-80df-16cd544087ad" parameterType="Hidden">
<name>UIPTaskName</name>
<dataDefinitionId>g359FC555-9CC7-47D4-8ED3-EF973E7D74D7</dataDefinitionId>
<value>Responsible Individual</value>
</variable>
<variable id="gb32914d5-6761-4e82-b571-c8944a796fd9" parameterType="Hidden">
<name>Search?</name>
<dataDefinitionId>g57201da8-62b4-46f2-9329-c71d86f39ffc</dataDefinitionId>
<value>True</value>
</variable>
</variables>
</workflow>
</workflows>
</wf>
滑轨
gc8f3715c-4a82-42d2-916c-51515083e7e5
UIPTaskName
g359FC555-9CC7-47D4-8ED3-EF973E7D74D7
负责人
搜索?
g57201da8-62b4-46f2-9329-c71d86f39ffc
真的
只需加载XML并重新编写,无需进行任何编辑,即可复制此行为。做:
var xdoc = XDocument.Parse(xml);
Debug.WriteLine(xdoc.ToXml());
生成输出:
<wf version="1.0a" xmlns:wf="http://example.com/workflow" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://example.com/workflow">
<assemblies />
<dataDefinitions />
<processes />
<workflows>
...
为什么会这样
wf
的名称空间:
xmlns="http://example.com/workflow"
xmlns:wf="http://example.com/workflow"
wf:
的意思与wf
元素和所有子元素完全没有前缀是一样的XElement
可以有效地使用前缀wf:
,或者根本不使用前缀,而不改变输出XML的语义XElement
如何在多个有效前缀之间进行选择呢,在forXElement
中,在写入时按添加顺序将名称空间/前缀属性对推送到,然后检查堆栈中元素名称空间的匹配情况——有效地按添加属性的相反顺序进行匹配xelents
将获得两个可能的有效前缀中的第二个,即无前缀wf:
前缀,而不是检查实际的名称空间名称(尽管它不应该),则可以通过将默认名称空间重新排序到根文档属性列表的开头来强制使用该前缀写出XML:
public static void ReorderDefaultNamespaceToBeginning(XElement xElement)
{
var attrArray = xElement.Attributes().ToArray();
int defaultIndex = -1;
for (int i = 0; i < attrArray.Length && defaultIndex == -1; i++)
{
var attr = attrArray[i];
if (attr.Name == XName.Get("xmlns", string.Empty))
defaultIndex = i;
}
if (defaultIndex < 0)
return; // No default namespace
int firstIndex = -1;
for (int i = 0; i < attrArray.Length && firstIndex == -1; i++)
{
if (i == defaultIndex)
continue;
var attr = attrArray[i];
if (attr.Name.NamespaceName == "http://www.w3.org/2000/xmlns/"
&& attr.Value == attrArray[defaultIndex].Value)
firstIndex = i;
}
if (defaultIndex != -1 && firstIndex != -1 && defaultIndex > firstIndex)
{
foreach (var attr in attrArray)
attr.Remove();
attrArray.Swap(defaultIndex, firstIndex);
foreach (var attr in attrArray)
xElement.Add(attr);
}
}
public static class ListHelper
{
public static void Swap<T>(this T[] list, int i, int j)
{
if (i != j)
{
T temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}
}
publicstaticvoid重新排序defaultnamespacetobegnning(XElement-XElement)
{
var attrray=xElement.Attributes().ToArray();
int defaultIndex=-1;
对于(int i=0;ifirstIndex)
{
foreach(attraray中的var attr)
attr.Remove();
Swap(defaultIndex,firstIndex);
foreach(attraray中的var attr)
添加(属性);
}
}
公共静态类ListHelper
{
公共静态无效交换(此T[]列表,int i,int j)
{
如果(i!=j)
{
T temp=列表[i];
列表[i]=列表[j];
列表[j]=温度;
}
}
}
(这利用了未记录的事实,即名称空间前缀按与外观相反的顺序进行检查。)完成此操作后,
wf:
前缀将返回。只需加载XML并再次写入,无需进行任何编辑,即可重现此行为。做:
var xdoc = XDocument.Parse(xml);
Debug.WriteLine(xdoc.ToXml());
生成输出:
<wf version="1.0a" xmlns:wf="http://example.com/workflow" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://example.com/workflow">
<assemblies />
<dataDefinitions />
<processes />
<workflows>
...
为什么会这样
wf
的名称空间:
xmlns="http://example.com/workflow"
xmlns:wf="http://example.com/workflow"
wf:
的意思与wf
元素和所有子元素完全没有前缀是一样的XElement
可以有效地使用前缀wf:
,或者根本不使用前缀,而不改变输出XML的语义XElement
如何在多个有效前缀之间进行选择呢,在forXElement
中,在写入时按添加顺序将名称空间/前缀属性对推送到,然后检查堆栈中元素名称空间的匹配情况——有效地按添加属性的相反顺序进行匹配xelents
将获得两个可能的有效前缀中的第二个,即无前缀wf:
前缀,而不是检查实际的名称空间名称(尽管它不应该),则可以通过将默认名称空间重新排序到根文档属性列表的开头来强制使用该前缀写出XML:
public static void ReorderDefaultNamespaceToBeginning(XElement xElement)
{
var attrArray = xElement.Attributes().ToArray();
int defaultIndex = -1;
for (int i = 0; i < attrArray.Length && defaultIndex == -1; i++)
{
var attr = attrArray[i];
if (attr.Name == XName.Get("xmlns", string.Empty))
defaultIndex = i;
}
if (defaultIndex < 0)
return; // No default namespace
int firstIndex = -1;
for (int i = 0; i < attrArray.Length && firstIndex == -1; i++)
{
if (i == defaultIndex)
continue;
var attr = attrArray[i];
if (attr.Name.NamespaceName == "http://www.w3.org/2000/xmlns/"
&& attr.Value == attrArray[defaultIndex].Value)
firstIndex = i;
}
if (defaultIndex != -1 && firstIndex != -1 && defaultIndex > firstIndex)
{
foreach (var attr in attrArray)
attr.Remove();
attrArray.Swap(defaultIndex, firstIndex);
foreach (var attr in attrArray)
xElement.Add(attr);
}
}
public static class ListHelper
{
public static void Swap<T>(this T[] list, int i, int j)
{
if (i != j)
{
T temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}
}
publicstaticvoid重新排序defaultnamespacetobegnning(XElement-XElement)
{
var attrray=xElement.Attributes().ToArray();
int defaultIndex=-1;
对于(int i=0;i