3

We're using Delphi 2007 and the oxmldom Open XML provider.

A normal situations input file looks similar to this:

<root>
  <child>Some Text</child>
</root>

Now we have to process an input file that uses the CDATA node type:

<root>
  <child><![CDATA[Some special Text]]></child>
</root>

Node.IsTextElement suddenly returns False, but Node.Text still works as expected.

I know that IXMLNode.IsTextElement is just a convenience method, but I find this behavior rather odd.

As a workaround we're now using this custom method:

class function TXmlUtils.IsTextOrCDataElement(ANode: IXMLNode): Boolean;
begin
  Result := False;
  if ANode.ChildNodes.Count = 0 then begin
    if ANode.NodeType in [ntText, ntCData] then begin
      Result := True;
    end;
  end else
  if ANode.ChildNodes.Count = 1 then begin
    if ANode.ChildNodes.First.NodeType in [ntText, ntCData] then begin
      Result := True;
    end;
  end;
end;

My question is: Why does IsTextElement not work with CDATA nodes and is there an easier workaround?

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
Jens Mühlenhoff
  • 14,565
  • 6
  • 56
  • 113
  • 3
    But... a CDATA element is *not* a TEXT element, so this behaviour is correct. Your work around seems not to be a work around at all but an implementation the correct behaviour you expect. – Ritsaert Hornstra Dec 07 '11 at 17:11
  • 1
    @RitsaertHornstra: you should post that as an answer to get credit for it. – Remy Lebeau Dec 07 '11 at 18:00
  • So the `Text` property works on different types of nodes and the `IsTextElement` only looks for nodes of type "TEXT"? Is that correct? – Jens Mühlenhoff Dec 08 '11 at 14:32
  • 2
    But @Ritsaert, IsTextElement method *also* returns True for non-text nodes. Specifically, it returns True for elements that have a single text-node child, such as `` in the example above. So, since it already differs from a simple `is` or `Supports` test, Jens's question of why it doesn't return True for *other* text-like nodes is legitimate. – Rob Kennedy Dec 08 '11 at 14:58
  • @Rob Kennedy - In `IsTextElement` there is `Element` word. And is `Element` which contains `Text` node. Literally, for me everything is fine with this function. – Pol Dec 08 '11 at 18:44
  • @Pol, IsTextElement returns true when called on an element that contains a single text node, but it also returns True when called directly on the text node, in which case there is no *element* at all. – Rob Kennedy Dec 08 '11 at 18:49
  • @Rob Kennedy, parent of text node is element. – Pol Dec 08 '11 at 18:52
  • @Pol: However there is no method like IsTextOrCDataElement, so that makes the IsTextElement function less useful. From a practical PoV there should have been a "TextAvailable" method. So My question is more like "Why is there no TextAvailable method?". – Jens Mühlenhoff Dec 09 '11 at 09:10
  • @Jens Mühlenhoff - Of course I agree with 'there should have been a "TextAvailable" method' – Pol Dec 09 '11 at 16:24
  • Does it make sense to QC this? – Jens Mühlenhoff Dec 09 '11 at 17:02

3 Answers3

2

It doesn't return true for Cdata nodes because that's just not the way it was written. It's unfortunate because consumers of XML data generally shouldn't be concerned with how text is represented in the serialized data. Your alternative is fine.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • I accepted this answer, because it confirms that I'm doing the right thing and that the `IsTextElement` is indeed insufficient for our requirements. – Jens Mühlenhoff Dec 09 '11 at 09:14
1

As Ritsaert Hornstra wrote in comment CDATA is not TEXT node of DOM tree. It's CDATA node.

Text property is something different. E.g. when current node is an attribute, Text will probably return value of this attribute.

If you want to check if current node is CDATA node or TEXT node, simply use Delphi is operator. There is also something like nodeType property which you are using anyway :-)

Pol
  • 5,064
  • 4
  • 32
  • 51
  • +1 because your answer is technically correct, but practically I was missing something like a "IsTextAvailable" method (see comments to the question). – Jens Mühlenhoff Dec 09 '11 at 09:13
-1

If you want to check if current node is CDATA node or TEXT node, simply use Delphi is operator. There is also something like nodeType property which you are using anyway :-)

? XML CDATA read 
Caleb
  • 124,013
  • 19
  • 183
  • 272