【问题标题】:Renaming XDocument Element Names重命名 XDocument 元素名称
【发布时间】:2019-09-30 17:59:40
【问题描述】:

我在重命名 XML 元素名称时遇到问题。我正在尝试实现以下目标。

输入:

<Addresses>
    <AddressItem>
        <AddressLine1>RZN850PXKYG</AddressLine1>
        <AddressLine2>RYK57IT7Y9Z</AddressLine2>
        <AddressType>Physical</AddressType>
        <City>Some City</City>
        <PostalCode>9999</PostalCode>
        <Province>Some Province</Province>
        <Suburb>Some Suburb</Suburb>
    </AddressItem>
</Addresses>

预期输出:

<b:Addresses>
    <b:AddressItem>
        <b:AddressLine1>RZN850PXKYG</b:AddressLine1>
        <b:AddressLine2>RYK57IT7Y9Z</b:AddressLine1>
        <b:AddressType>Physical</b:AddressType>
        <b:City>Some City</b:City>
        <b:PostalCode>9999</b:PostalCode>
        <b:Province>Some Province</b:Province>
        <b:Suburb>Some Suburb</b:Suburb>
    </b:AddressItem>
</b:Addresses>

之前我已经成功地添加了属性并使用类似的东西重命名了元素:

var xmlDoc = XDocument.Parse(requestObj);

foreach (var element in xmlDoc.Descendants())
{
    if (element.Name.LocalName.StartsWith("something"))
    {
        //example rename element
        element.Name = "request";

        XNamespace b = "http://schemas.something.org/bla/07/WebServices.Stuff";
        XNamespace i = "http://www.w3.org/2001/XMLSchema-instance";

        //set it's attributes
        element.SetAttributeValue(XNamespace.Xmlns + "b", b);
        element.SetAttributeValue(XNamespace.Xmlns + "i", i);
    }
}

我试图通过简单地使用下面的代码来达到我的预期结果,但冒号似乎给我带来了问题:

foreach (var element in xmlDoc.Descendants())
{
    element.Name = "b:" + element.Name;
}

我使用收到的错误消息 (System.Xml.XmlException: 'The ':' character, hexadecimal value 0x3A, cannot be included in a name.') 进行了搜索,但似乎没有一个解决方案适用于需要递归重命名的元素。

【问题讨论】:

  • 你试过用谷歌搜索你的错误信息吗?我刚刚复制了您的错误并将其粘贴到 Google 中。这是出现的第一件事:stackoverflow.com/questions/2575546/…
  • 元素&lt;b:Addresses&gt; 不能没有与b 对应的命名空间声明,例如xmlns:b="https://whatever-you-want-here"。如果没有命名空间声明,则您的 XML 格式不正确。你想要什么命名空间?是"http://schemas.something.org/bla/07/WebServices.Stuff"吗?
  • @dbc 是的,我现在正在一个单独的过程中将名称空间减速添加到 xml,然后尝试手动更改元素。

标签: c# xml xml-parsing


【解决方案1】:

假设&lt;Addresses&gt;是您XML文档中的某个嵌套元素,并且某个上层节点应该声明一个命名空间xmlns:b="http://schemas.something.org/bla/07/WebServices.Stuff",您可以如下修改您的XML:

XNamespace newNamespace = "http://schemas.something.org/bla/07/WebServices.Stuff";

// Move Addresses elements and children into the new namespace
foreach (var e in xmlDoc.Descendants().Where(a => a.Name.LocalName == "Addresses").SelectMany(a => a.DescendantsAndSelf()))
{
    e.Name = newNamespace + e.Name.LocalName;
}

// Optionally assign the namespace prefix "b" to some container element in scope.
xmlDoc.Root.SetAttributeValue(XNamespace.Xmlns + "b", newNamespace.NamespaceName);

注意事项:

  1. 您正在尝试将选定的XElement 对象的Name 属性修改为"b:"+element.Name;,但是XElement.Name 不是string,它是一个XName,它封装了一个XML 命名空间和本地name -- 不是 XML 命名空间 prefix 和本地名称。因此,尝试为 Name 分配特定前缀失败,并引发异常。

    在 LINQ-to-XML 中,XElement 对象不知道它们的命名空间前缀。他们知道自己的实际命名空间。只有在将 XElement 输出到 XML 字符串时,XmlWriter 才会尝试通过在范围内查找 xmlns declaration 来确定命名空间前缀——或者如果范围内没有,那么它将自动发出适当的 xmlns 声明当前元素。

    因此,要将元素修改为类似于&lt;b:Addresses&gt;,您必须将其实际命名空间 修改为b: 应对应的任何内容。现在,您可能并不关心选择的精确前缀,但如果您这样做,您可以随后在范围内的某个适当元素上指定一个前缀,例如根元素。

    演示小提琴 #1 here.

  2. 如果您不关心使用的具体前缀,您可以完全省略// Optionally 代码,.Net 的XmlWriter 会自动为您添加命名空间声明。

    演示小提琴 #2 here.

【讨论】:

  • 非常感谢您的深入解释和示例,如果我没有其他问题,我现在将测试所有这些并将其标记为正确答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多