Как добавить пространство имен в msxml DOMDocument?
Как добавить схему в IXMLDOMDocument
?
Например, я хочу сгенерировать 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
быть выпущенным.
Так что теперь я сдаюсь и спрашиваю Stackru.
Вместо того, чтобы пытаться построить XML-документ правильным способом, я всегда мог бы использовать StringBuilder
создать XML вручную, а затем проанализировать его в объект XML-документа.
Но я бы предпочел сделать это правильно.
1 ответ
Хитрость заключается в том, чтобы реализовать 2-й уровень W3C DOM и метод 3 createElementNS
:
Создает элемент с указанным URI пространства имен и квалифицированным именем.
Синтаксис
element = document.createElementNS(namespaceURI, qualifiedName);
Однако MSXML 6 поддерживает только DOM Level 1.
К счастью, в W3C DOM Level 1 был метод для создания элемента с пространством имен: createNode
:
Создает узел, используя предоставленный тип, имя и пространство имен.
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");