【问题标题】:Can't add namespace to XML at runtime无法在运行时将命名空间添加到 XML
【发布时间】:2009-10-22 14:55:03
【问题描述】:

我有一个需要在运行时应用命名空间的 XML 文件。我在网上搜索过,大多数示例似乎都建议使用“SetAttributeValue”函数。当我使用下面的代码时,当我尝试“ToString()”并出现以下错误时会引发异常:

The prefix '' cannot be redefined from '' to 'http://schemas.datacontract.org/2004/07/' within the same start element tag.

有什么想法吗?

XDocument data = XDocument.Parse("<Root><Stuff>Test</Stuff></Root>");

string ns = "http://schemas.datacontract.org/2004/07/";

data.Root.SetAttributeValue("xmlns",ns);

SaveFile(data.ToString());

【问题讨论】:

    标签: .net xml namespaces


    【解决方案1】:

    聚会有点晚了……

    XNamespace ns = "http://schemas.datacontract.org/2004/07/"; 
    XDocument xdoc = XDocument.Parse("<Root><Stuff>Test</Stuff></Root>");
    foreach (var node in xdoc.Descendants()) { node.Name = ns + node.Name.LocalName; }
    xdoc.Dump();
    
    <Root xmlns="http://schemas.datacontract.org/2004/07/">
      <Stuff>Test</Stuff>
    </Root> 
    

    【讨论】:

      【解决方案2】:

      进行 XSLT 转换:

      <xsl:stylesheet
        version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns="your.target.default.namespace"
      >
        <!-- 
          the "identity template" copies everything verbatim 
        -->
        <xsl:template match="node() | @*">
          <xsl:copy>
            <xsl:apply-templates select="node() | @*" />
          </xsl:copy>
        </xsl:template>
      
        <!-- 
          this template creates new elements that 
          are in "your.target.default.namespace"
          by default
        -->
        <xsl:template match="*">
          <xsl:element name="{local-name()}">
            <xsl:apply-templates select="node() | @*" />
          </xsl:element>
        </xsl:template>
      
      </xsl:stylesheet>
      

      上面获取一个无命名空间的输入文档,并复制它。只有元素节点被重新创建(通过第二个模板)。

      重新创建元素节点会使它们位于 XSLT 样式表所在的命名空间中,这里是“your.target.default.namespace”。

      用你的例子,我会得到:

      <Root xmlns="http://schemas.datacontract.org/2004/07/">
        <Stuff>Test</Stuff>
      </Root>
      

      【讨论】:

        【解决方案3】:

        默认命名空间实际上是 XElement 固有的,它不允许您通过操作属性来重新定义它。元素的命名空间作为其 XName 的一部分公开。因此,要更改元素的命名空间,您必须重命名它。

        XDocument data = XDocument.Parse("<Root><Stuff>Test</Stuff></Root>");
        
        XNamespace ns = "http://schemas.datacontract.org/2004/07/";
        
        data.Root.Name = ns + data.Root.Name.LocalName;
        

        【讨论】:

          【解决方案4】:

          你不能那样做。命名空间是 DOM 的基础。我现在能想到的唯一方法是在整个 XML 文本上使用 String.Replace 添加它,然后重新解析结果。

          【讨论】:

            【解决方案5】:

            这些属性前段时间也困扰着我。我在创建一个简单的播客时使用XNamespace class 解决了这个问题。以下是我的应用程序的示例代码:

            XDocument xmlDocument = new XDocument(
                            new XDeclaration("1.0", "utf-8", "yes")
                            );
            
            XNamespace itunesNamespace = "http://www.itunes.com/dtds/podcast-1.0.dtd";
            XElement xmlRssElement = new XElement("rss", new XAttribute(XNamespace.Xmlns + "itunes", itunesNamespace), new XAttribute("version", "2.0"));
            
            XElement xmlChannelElement = new XElement("channel",
                                         new XElement("title", "title"), 
                                         new XElement(itunesNamespace + "explicit", "No"));
            
            xmlRssElement.Add(xmlChannelElement);
            xmlDocument.Add(xmlRssElement);
            xmlDocument.Save(@"sample-" + DateTime.Now.Ticks + ".xml");
            

            请注意,一些代码已被删除以进行澄清

            您可以使用 XDocument.Parse() 获取原始文档,然后在保存文档之前从那里动态添加命名空间,就像在我的代码中完成的那样

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2023-03-24
              • 2017-09-21
              • 2013-09-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多