Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# XDocument保存删除节点前缀_C#_Xml_Linq To Xml - Fatal编程技术网

C# XDocument保存删除节点前缀

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文档(自制),其结构如下:

<?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
    元素和所有子元素完全没有前缀是一样的

  • 因此,当将自身写回XML时,
    XElement
    可以有效地使用前缀
    wf:
    ,或者根本不使用前缀,而不改变输出XML的语义

  • 那么
    XElement
    如何在多个有效前缀之间进行选择呢,在for
    XElement
    中,在写入时按添加顺序将名称空间/前缀属性对推送到,然后检查堆栈中元素名称空间的匹配情况——有效地按添加属性的相反顺序进行匹配

  • 因此,您的
    xelents
    将获得两个可能的有效前缀中的第二个,即无前缀

  • 总之,带前缀的XML和不带前缀的XML在语义上是相同的。任何适当的XML解析器都不应该关心这种差异

    但是,如果出于任何原因,您正在使用的某些代码采用了
    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
    元素和所有子元素完全没有前缀是一样的

  • 因此,当将自身写回XML时,
    XElement
    可以有效地使用前缀
    wf:
    ,或者根本不使用前缀,而不改变输出XML的语义

  • 那么
    XElement
    如何在多个有效前缀之间进行选择呢,在for
    XElement
    中,在写入时按添加顺序将名称空间/前缀属性对推送到,然后检查堆栈中元素名称空间的匹配情况——有效地按添加属性的相反顺序进行匹配

  • 因此,您的
    xelents
    将获得两个可能的有效前缀中的第二个,即无前缀

  • 总之,带前缀的XML和不带前缀的XML在语义上是相同的。任何适当的XML解析器都不应该关心这种差异

    但是,如果出于任何原因,您正在使用的某些代码采用了
    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