Не удается добавить пространство имен в XML во время выполнения - PullRequest
1 голос
/ 22 октября 2009

У меня есть 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());

Ответы [ 5 ]

2 голосов
/ 26 августа 2010

Немного опоздал на вечеринку ...

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> 
1 голос
/ 29 ноября 2009

Пространство имен по умолчанию на самом деле присуще 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;
1 голос
/ 22 октября 2009

Выполнить 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>
0 голосов
/ 23 октября 2009

Эти атрибуты тоже давали мне покои. Я решил это с помощью класса XNamespace при создании простого подкаста. Ниже приведен пример кода из моего приложения:

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 () и динамически добавлять пространство имен, как это делается в моем коде перед сохранением документа

0 голосов
/ 22 октября 2009

Вы не можете этого сделать. Пространства имен являются фундаментальными для DOM. Единственный способ, о котором я могу думать прямо сейчас, - это добавить его, используя String.Replace, ко всему тексту XML, а затем проанализировать результат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...