重命名XDocument元素名称

时间:2019-09-30 17:59:40

标签: c# xml xml-parsing

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

  

输入:

 if(getIntent().getIntExtra("number",-1) ==2)
    {
        // what do you want to do...
    }
  

预期输出:

<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; } )进行了搜索,但是似乎没有一种解决方案适用于需要递归重命名的元素。

1 个答案:

答案 0 :(得分:1)

假设<Addresses>是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. 您正在尝试将所选Name对象的XElement属性修改为"b:"+element.Name;,但是XElement.Name不是string,它是是XName,其中封装了XML名称空间和本地名称-而不是XML名称空间前缀和本地名称。因此,尝试为Name分配一个特定的前缀会失败,并引发异常。

    在LINQ-to-XML中,XElement对象不知道其名称空间前缀。他们知道他们的实际名称空间。只有在将XElement输出到XML字符串时,XmlWriter才会尝试通过在范围内寻找xmlns declaration来确定名称空间前缀-否则,如果它不在范围内,它将发出一个适当的名称自动在当前元素上进行xmlns声明。

    因此,要将元素修改为类似于<b:Addresses>的元素,必须将其实际名称空间修改为b:应该对应的内容。现在,您可能并不在乎所选择的精确前缀,但是如果您这样做了,则可以随后在范围中的某个适当元素(例如根元素)上指定一个。

    演示小提琴#1 here

  2. 如果您不关心所使用的特定前缀,则可以完全省略// Optionally代码,.Net的XmlWriter将自动为您添加名称空间声明。

    演示小提琴#2 here

相关问题