View Issue Details

IDProjectCategoryView StatusLast Update
0022299FPCFCLpublic2013-11-05 15:13
ReporterDaniel Gaspary Assigned ToSergei Gorelkin  
PrioritynormalSeverityminorReproducibilityalways
Status assignedResolutionopen 
Platformx86-64OSLinux 
Product Version2.6.1 
Summary0022299: WriteXML generating incorrect file
DescriptionThe Attached Program was created to generate the following XML:

<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
  <script xlink:href="cool-script.js" type="text/ecmascript"/>
</svg>

The program finishes without problems. But the generated file misses the "xmlns:xlink=..." attribute and this causes an error when trying to open the file with Firefox or another browser.

On Other hand, an Execution error is raised if the line 20 is uncommented (setAttributeNS) and the lines 21, 22 and 23 are commented.
TagsXML
Fixed in Revision
FPCOldBugId
FPCTarget
Attached Files

Relationships

related to 0025183 closedSergei Gorelkin Patch to create an XPath Namespace Resolver 

Activities

2012-06-22 02:42

 

project1.lpr (773 bytes)

Sergei Gorelkin

2012-06-22 12:13

developer   ~0060647

You are creating ScriptNode using CreateElement method, which creates an element without namespace. The specification says that such documents must fail to serialize (however it doesn't say anything about behavior of DOM). The only bug in fcl-xml is that this isn't properly checked.

Using CreateElementNS yields the necessary result:

ScriptNode:=XMLDoc.CreateElementNS('http://www.w3.org/2000/svg','script');

but the 'xmlns:xlink' attribute appears on the 'script' element. If you want it to appear on 'svg', you should set it there.

Also I couldn't reproduce the runtime error with 2.7.1.

Daniel Gaspary

2012-06-22 16:32

reporter   ~0060650

"Using CreateElementNS yields the necessary result"

True, the Specification says to avoid mix NS and not NS aware methods.

"but the 'xmlns:xlink' attribute appears on the 'script' element. If you want it to appear on 'svg', you should set it there."

Ok, but is possible to create the below file with fcl-xml?

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
  <script1 xlink:href="cool-script.js"/>
  <script2 xlink:href="cool-script.js"/>
  <script3 xlink:href="cool-script.js"/>
</svg>

The attached project2.lpr instead create:

<svg xmlns="http://www.w3.org/2000/svg">
  <script1 xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="cool-script.js"/>
  <script2 xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="cool-script.js"/>
  <script3 xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="cool-script.js"/>
</svg>

Both are valid XML files, but the First is a much more compact form.

At The specification[1] you can find:

"As far as the DOM is concerned, special attributes used for declaring XML namespaces are still exposed and can be manipulated just like any other attribute."

Is this true to fcl-xml ? I have tried and was not possible find the declarative nodes(example: xmlns:xlink="http...") using GetAtrribute/GetAtrributeNS.

Examinating the DOM code, it seems to just store references to nsPrefix and nsURI, it doesnt really create attribute nodes. So is not possible to move the attribute xmlns:xlink="http://www.w3.org/1999/xlink" to the svg node.

[1] http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#Namespaces-Considerations

2012-06-22 16:33

 

project2.lpr (707 bytes)

2012-06-22 19:37

 

compact.xml (254 bytes)   
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
  <script1 xlink:href="cool-script.js"/>
  <script2 xlink:href="cool-script.js"/>
  <script3 xlink:href="cool-script.js"/>
</svg>
compact.xml (254 bytes)   

2012-06-22 19:40

 

ReadXmlWithNamespaces.pas (971 bytes)   
program ReadXmlWithNamespaces;
{$mode objfpc}{$H+}

uses
 classes, sysutils, DOM, XMLRead, XMLWrite;

var
  Parser: TDOMParser;
  Src: TXMLInputSource;
  TheDoc: TXMLDocument;
  astream: TStream;

  SvgNode: TDOMNode;

procedure PrintAttValue(attName: string);
var
   s: string;
begin
     s:=TDOMElement(SvgNode).GetAttribute(attName);
     with SvgNode do
       WriteLn(attName + '=>' + s);
end;

begin
  try
     Parser := TDOMParser.Create;
     Parser.Options.Namespaces:=true;

     astream:=TFileStream.Create('/tmp/compact.xml', fmOpenRead);
     Src := TXMLInputSource.Create(astream);

     Parser.Parse(Src, TheDoc);

     SvgNode:=TheDoc.DocumentElement;

     //The Values are printed, so the Attribute nodes were created for xmlns declarations
     PrintAttValue('xmlns'); //Print "http://www.w3.org/2000/svg"
     PrintAttValue('xmlns:xlink'); //Print "http://www.w3.org/1999/xlink"

  finally
    Src.Free;
    Parser.Free;
    astream.Free;
  end;
end.
ReadXmlWithNamespaces.pas (971 bytes)   

Daniel Gaspary

2012-06-22 19:43

reporter   ~0060651

The ReadXmlWithNamespaces.pas shows that the TDOMParser class when is reading a "compact" XML (as mentioned at the prior comment) with namespaces actually create attributes nodes contrary to dom behaviour.

Sergei Gorelkin

2012-06-22 20:04

developer   ~0060652

You should explicitly attach an 'xmlns:xlink' attribute to the 'svg' element:

 XmlDoc := TXMLDocument.Create;
 SvgNode:=XMLDoc.CreateElementNS('http://www.w3.org/2000/svg', 'svg');
 SvgNode.SetAttributeNS('http://www.w3.org/2000/xmlns/','xmlns:xlink','http://www.w3.org/1999/xlink'); //<--here

 XMLDoc.AppendChild(SvgNode);
 ScriptNode:=XMLDoc.CreateElementNS('http://www.w3.org/2000/svg','script');
 ScriptNode.SetAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', 'cool-script.js');

DOM doesn't create additional attributes automatically, the namespace fixup only happens when writing the document out (it is rather complex process which may also change prefixes of attributes in case of conflicting namespaces).

Daniel Gaspary

2012-06-23 00:51

reporter   ~0060655

"SvgNode.SetAttributeNS('http://www.w3.org/2000/xmlns/','xmlns:xlink','http://www.w3.org/1999/xlink'); [^] //<--here"

I never would guess that solution.

Thank you, Sergei.

Daniel Gaspary

2013-11-05 12:42

reporter   ~0071154

This issue can be closed.

Sergei Gorelkin

2013-11-05 15:13

developer   ~0071156

I keep it open because I want to add the check for non-namespaced elements during serialization. It is trivial but requires extensive testing for possible side effects.

Issue History

Date Modified Username Field Change
2012-06-22 02:42 Daniel Gaspary New Issue
2012-06-22 02:42 Daniel Gaspary File Added: project1.lpr
2012-06-22 11:31 Sergei Gorelkin Status new => assigned
2012-06-22 11:31 Sergei Gorelkin Assigned To => Sergei Gorelkin
2012-06-22 12:13 Sergei Gorelkin Note Added: 0060647
2012-06-22 16:32 Daniel Gaspary Note Added: 0060650
2012-06-22 16:33 Daniel Gaspary File Added: project2.lpr
2012-06-22 19:37 Daniel Gaspary File Added: compact.xml
2012-06-22 19:40 Daniel Gaspary File Added: ReadXmlWithNamespaces.pas
2012-06-22 19:43 Daniel Gaspary Note Added: 0060651
2012-06-22 20:04 Sergei Gorelkin Note Added: 0060652
2012-06-23 00:51 Daniel Gaspary Note Added: 0060655
2013-10-13 21:22 Marco van de Voort Relationship added related to 0025183
2013-10-16 00:46 Daniel Gaspary Tag Attached: XML
2013-11-05 12:42 Daniel Gaspary Note Added: 0071154
2013-11-05 15:13 Sergei Gorelkin Note Added: 0071156