Как добавить пространство имен в DOMDocument msxml?

Как добавить схему в _1 _?

Например, я хочу сгенерировать XML:

<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
   <Relationship Id="rId1" Type="Frob" Target="Grob"/>
</Relationships>

Я могу создать объект DOMDocument60 (псевдокод):

DOMDocument60 doc = new DOMDocument60();

IXMLDOMElement relationships = doc.appendChild(doc.createElement("Relationships"));

IXMLDOMElement relationship = relationships.appendChild(doc.createElement("Relationship"));
   relationship.setAttribute("Id", "rId1");
   relationship.setAttribute("Type", "Frob");
   relationship.setAttribute("Target", "Grob");

Теперь возникает вопрос, как добавить пространство имен.

Как добавить пространство имен?

Если я выберу очевидное решение, установив атрибут узла Взаимосвязи с именем xmlns:

<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">

через что-то вроде:

relationships.setAttribute("xmlns", 
      "http://schemas.openxmlformats.org/package/2006/relationships");

Когда документ сохраняется, это приводит к тому, что полученный xml неверен:

<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
   <Relationship Id="rId1" Type="Frob" Target="Grob" xmlns=""/>
</Relationships>

Он помещает пустые xmlns атрибуты на каждый второй элемент. В этом небольшом тестовом документе xmlns неправильно применяется только к одному элементу. В реальном мире есть десятки или несколько миллионов других элементов с пустым атрибутом xmlns.

namespaceURI свойство

Я попытался установить свойство namespaceURI для Relationships элемент:

relationshps.namespaceURI := "http://schemas.openxmlformats.org/package/2006/relationships"; 

но свойство доступно только для чтения.

схемы Свойство

У документа есть свойство schemas, который получает или устанавливает объект XMLSchemaCache. Но для этого требуется фактический документ схемы. Например. попытка просто установить схему не работает:

schemas = new XMLSchemaCache60();
schemas.add('', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main');
doc.schemas := schemas;

Но это пытается фактически загрузить URL-адрес схемы, а не не загружать схему, потому что это не URI.

Возможно, мне придется случайным образом попробовать другие вещи:

schemas = new XMLSchemaCache60();
schemas.add('http://schemas.openxmlformats.org/spreadsheetml/2006/main', null);
doc.schemas := schemas;

Но это не вызывает излучения xmlns.

Итак, теперь я сдаюсь и спрашиваю Stackoverflow.

Вместо того, чтобы пытаться правильно построить XML-документ, я всегда мог бы использовать StringBuilder для создания XML вручную, а затем преобразовать его в объект XML-документа.

Но я бы предпочел сделать это правильно.


person Ian Boyd    schedule 15.03.2016    source источник


Ответы (1)


Уловка состоит в том, чтобы понять, что W3C DOM Level 2 и 3 имеет метод createElementNS ????:

Создает элемент с указанным URI пространства имен и квалифицированным именем.

Синтаксис

element = document.createElementNS(namespaceURI, qualifiedName);

Однако MSXML 6 поддерживает только DOM уровня 1.

К счастью, в W3C DOM Level 1 был метод для создания элемента с пространством имен: _ 3_ ????:

Создает узел, используя предоставленный тип, имя и пространство имен.

HRESULT createNode(VARIANT Type, BSTR name, BSTR namespaceURI, out IXMLDOMNode node);

Таким образом, мое решение состоит в том, что мне нужно изменить:

relationships: IXMLDOMElement = doc.createElement("Relationships"); 

в:

const NODE_ELEMENT: Integer = 1;
const ns: string = "http://schemas.openxmlformats.org/package/2006/relationships";

relationships: IXMLDOMElement = doc.createNode(NODE_ELEMENT, "Relationships", namespace); 

Отстойная часть состоит в том, что каждый элемент должен быть создан в этом пространстве имен:

function AddElementNS(IXMLDOMNode parentNode, String tagName, String namespaceURI): IXMLDOMElement;
{
   doc: IXMLDOMDocument = parentNode as IXMLDOMDocument;
   if (doc == null) 
      doc = parentNode.ownerDocument;

   if (namespaceURI <> "")
      Result = doc.createNode(NODE_ELEMENT, tagName, namespaceURI)
   else
      Result = doc.createElement(tagName);

   parentNode.appendChild(Result);
}

relationships: IXMLDOMElement = AddElementNS(doc, "Relationships", ns);

relationship: IXMLDOMElement = AddElementNS(relationships, "Relationship", ns);
   relationship.setAttribute("Id", "rId1");
   relationship.setAttribute("Type", "Frob");
   relationship.setAttribute("Target", "Grob");       

Бонусное чтение

person Ian Boyd    schedule 17.03.2016
comment
Спасибо за совет. У меня была такая же проблема, теперь с вашей помощью я получил хороший .xml с правильным пространством имен. - person junpet; 14.02.2020