DeleteTopElement (XmlDoc subroutine): Difference between revisions

From m204wiki
Jump to navigation Jump to search
mNo edit summary
mNo edit summary
Line 2: Line 2:


This subroutine removes the top <var>Element</var> from an <var>XmlDoc</var>, and it
This subroutine removes the top <var>Element</var> from an <var>XmlDoc</var>, and it
makes its children be the &ldquo;middle siblings&rdquo; of the left and right siblings (<var>Comments</var> or <var>PIs</var>)
makes the deleted <var>Element</var>'s children be the &ldquo;middle siblings&rdquo; of its left and right siblings (<var>Comments</var> or <var>PIs</var>).
of the deleted <var>Element</var>.
<ul>
<ul>
<li>The deleted element may not have more than one
<li>The deleted <var>Element</var> may not have more than one
<var>Element</var> child.
<var>Element</var> child.
<li>The deleted element may not have a <var>Text</var> child.
<li>The deleted <var>Element</var> may not have a <var>Text</var> child.
</ul>
</ul>
In common usage, the <var>Element</var> child of the deleted <var>Element</var> will become the
In common usage, the <var>Element</var> child of the deleted <var>Element</var> will become the
new top <var>Element</var> of the <var>XmlDoc</var>.
new top <var>Element</var> of the <var>XmlDoc</var>.
__TOC__


==Syntax==
==Syntax==
Line 24: Line 24:
<ul>
<ul>
<li><var>DeleteTopElement</var> is a convenient, better-performing alternative to using
<li><var>DeleteTopElement</var> is a convenient, better-performing alternative to using
<var>[[AddSubtree (XmlDoc/XmlNode function)|AddSubtree]]</var> to copy all but the top Element (or in multiple iterations,
<var>[[AddSubtree (XmlDoc/XmlNode function)|AddSubtree]]</var> to copy all but the top <var>Element</var> (or in multiple iterations, removing successive top <var>Elements</var>) from an <var>XmlDoc</var>.
removing successive top Elements) from an <var>XmlDoc</var>.
   
   
For example, you can use it to remove the SOAP wrappers from an <var>XmlDoc</var>.
For example, you can use it to remove the SOAP wrappers from an <var>XmlDoc</var>.
Line 46: Line 45:
</data>
</data>
</nowiki></p>
</nowiki></p>
 
<li>The remaining considerations for using <var>DeleteTopElement</var>
<div id="wrap2"></div>
concern the occurrence of namespace declarations in the
<li>Using <var>DeleteTopElement</var> requires understanding how it handles
<var>XmlDoc</var>; there are a few details to explain how they are
the occurrence of namespace declarations in the
manipulated, and to explain how the performance of
<var>XmlDoc</var>. As shown in the &ldquo;SOAP wrapper removal&rdquo; example above,
<var>DeleteTopElement</var> is affected.
<p>
As shown in the &ldquo;SOAP wrapper removal&rdquo; example above,
<var>DeleteTopElement</var> will remove from the <var>XmlDoc</var> any namespace
<var>DeleteTopElement</var> will remove from the <var>XmlDoc</var> any namespace
declarations (in this example, <code>xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"</code>)
declarations (in this example, <code>xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"</code>)
that '''are not''' referenced after removing the top Element.
that '''are not''' referenced after removing the top <var>Element</var>.
Note that a variant on the above example can occur using a
<p>Here is a variation of the above example that uses a
default namespace declaration:</p>
default namespace declaration:</p>
<p class="code"><nowiki><Envelope xmlns"http://schemas.xmlsoap.org/soap/envelope/">
<p class="code"><nowiki><Envelope xmlns"http://schemas.xmlsoap.org/soap/envelope/">
Line 80: Line 76:
removed, even though, strictly speaking, it is not needed.
removed, even though, strictly speaking, it is not needed.
   
   
In addition, <var>DeleteTopElement</var> will move to the new top Element
In addition, <var>DeleteTopElement</var> will move to the new top <var>Element</var>
any namespace declarations that '''do''' continue to be
any namespace declarations that '''do''' continue to be
referenced after the top Element deletion:
referenced after the top <var>Element</var> deletion:
<p class="code"><nowiki>%n = %d:AddElement('foo', , 'u:uri')
<p class="code">%n = %d:AddElement('foo', , 'u:uri')
%n:AddElement('bar', , 'u:uri')
%n:AddElement('bar', , 'u:uri')
%d:Print
%d:Print
Line 89: Line 85:
Print 'After deletion:'
Print 'After deletion:'
%d:Print
%d:Print
</nowiki></p>
</p>
The result of the above <var class="product">User Language</var> fragment is:
The result of the above <var class="product">User Language</var> fragment is:
<p class="output"><nowiki><foo xmlns="u:uri">
<p class="output"><nowiki><foo xmlns="u:uri">
Line 105: Line 101:
For a detailed explanation of when the cost of <var>DeleteTopElement</var>
For a detailed explanation of when the cost of <var>DeleteTopElement</var>
might vary with the size of the <var>XmlDoc</var>,
might vary with the size of the <var>XmlDoc</var>,
there are three reasons that the descendants
consider the three reasons that the descendants
of the new top Element need to be recursively visited:
of the new top <var>Element</var> need to be recursively visited:
<ol>
<ol>
<li>Fixing references to moved namespace declaration
<li>Fixing references to the moved namespace declaration
<p>
<p>
As mentioned above, one or more namespace declarations can be moved
As mentioned above, one or more namespace declarations can be moved
Line 114: Line 110:
Having done that, any references to the moved namespace must be fixed.
Having done that, any references to the moved namespace must be fixed.
A count is kept to the total references to moved namespace
A count is kept to the total references to moved namespace
declarations; when this goes to zero, there is no more need to do this.
declarations; when this goes to zero, there is no further need to do this.
So, for example:</p>
So, for example:</p>
<p class="code"><nowiki><p:oldTop xmlns:p="p:uri">
<p class="code"><nowiki><p:oldTop xmlns:p="p:uri">
Line 122: Line 118:
</p:oldTop>
</p:oldTop>
</nowiki></p>
</nowiki></p>
The <code>p:newTop</code> element needs to have it's namespace reference fixed, but that is the only reference to it, so there is no need to visit <code>child</code>.</li>
The <code>p:newTop</code> element needs to have its namespace reference fixed, but that is the only reference to it, so there is no need to visit <code>child</code>.</li>
<li>Fixing pointers to a deleted namespace declaration
<li>Fixing pointers to a deleted namespace declaration
<p>
<p>
When a namespace declaration is deleted, it may be pointed to by other
When a namespace declaration is deleted, it may be pointed to by other
namespace declarations (there is a graph of them in the <var>XmlDoc</var>); these
namespace declarations (there is a graph of them in the <var>XmlDoc</var>). These
pointers need to be fixed to point to the first non-deleted
pointers need to be fixed to point to the first non-deleted
declaration following the deleted one.
declaration following the deleted one.
Line 148: Line 144:
namespace declaration to occur on an ancestor.
namespace declaration to occur on an ancestor.
This state is fixed up if <var>DeleteTopElement</var> deletes a non-null
This state is fixed up if <var>DeleteTopElement</var> deletes a non-null
namespace declaration (as happens in the second &ldquo;SOAP wrapper
namespace declaration (as happens in the [[#wrap2|second &ldquo;SOAP wrapper
removal&rdquo; example above, the one using a default namespace).
removal&rdquo; example]] above).
The need to set this state is eliminated in descendants of an Element
The need to set this state is eliminated in descendants of an <var>Element</var>
that have a default namespace declaration (either null or not).
that have a default namespace declaration (either null or not).
So, for example:</p>
So, for example:</p>

Revision as of 19:26, 3 June 2011

Delete top element from XmlDoc (XmlDoc class)

[Introduced in Sirius Mods 7.8]


This subroutine removes the top Element from an XmlDoc, and it makes the deleted Element's children be the “middle siblings” of its left and right siblings (Comments or PIs).

  • The deleted Element may not have more than one Element child.
  • The deleted Element may not have a Text child.

In common usage, the Element child of the deleted Element will become the new top Element of the XmlDoc.

Syntax

doc:DeleteTopElement

Syntax terms

doc An XmlDoc object expression.

Usage notes

  • DeleteTopElement is a convenient, better-performing alternative to using AddSubtree to copy all but the top Element (or in multiple iterations, removing successive top Elements) from an XmlDoc. For example, you can use it to remove the SOAP wrappers from an XmlDoc. If the contents of %xdoc are:

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <data> ... </data> </soap:Body> </soap:Envelope>

    Then the following User Language fragment:

    %xdoc:DeleteTopElement %xdoc:DeleteTopElement

    Results in the following contents of %xdoc:

    <data> ... </data>

  • Using DeleteTopElement requires understanding how it handles the occurrence of namespace declarations in the XmlDoc. As shown in the “SOAP wrapper removal” example above, DeleteTopElement will remove from the XmlDoc any namespace declarations (in this example, xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/") that are not referenced after removing the top Element.

    Here is a variation of the above example that uses a default namespace declaration:

    <Envelope xmlns"http://schemas.xmlsoap.org/soap/envelope/"> <Body> <data xmlns=""> ... </data> </Body> </Envelope>

    Then the following User Language fragment:

    %xdoc:DeleteTopElement %xdoc:DeleteTopElement

    Results in the following contents of %xdoc:

    <data xmlns=""> ... </data>

    As seen in this example, the null namespace declaration is not removed, even though, strictly speaking, it is not needed.

    In addition, DeleteTopElement will move to the new top Element any namespace declarations that do continue to be referenced after the top Element deletion:

    %n = %d:AddElement('foo', , 'u:uri') %n:AddElement('bar', , 'u:uri') %d:Print %d:DeleteTopElement Print 'After deletion:' %d:Print

    The result of the above User Language fragment is:

    <foo xmlns="u:uri"> <bar/> </foo> After deletion: <bar xmlns="u:uri"/>

  • The performance of DeleteTopElement should always be significantly better than an approach using AddSubtree, and in many cases, it is constant, regardless of the size of the XmlDoc. For a detailed explanation of when the cost of DeleteTopElement might vary with the size of the XmlDoc, consider the three reasons that the descendants of the new top Element need to be recursively visited:
    1. Fixing references to the moved namespace declaration

      As mentioned above, one or more namespace declarations can be moved from the deleted element to the new top element. Having done that, any references to the moved namespace must be fixed. A count is kept to the total references to moved namespace declarations; when this goes to zero, there is no further need to do this. So, for example:

      <p:oldTop xmlns:p="p:uri"> <p:newTop> <child/> </p:newTop> </p:oldTop>

      The p:newTop element needs to have its namespace reference fixed, but that is the only reference to it, so there is no need to visit child.
    2. Fixing pointers to a deleted namespace declaration

      When a namespace declaration is deleted, it may be pointed to by other namespace declarations (there is a graph of them in the XmlDoc). These pointers need to be fixed to point to the first non-deleted declaration following the deleted one. This is not needed by the descendants of any element that has a namespace declaration (in the original XmlDoc). So, for example:

      <p:oldTop xmlns:p="p:uri"> <newTop> <q:child xmlns:q="q:uri"> <grandchild/> </q:child> </newTop> </p:oldTop>

      Both newTop and q:child need to have their namespace pointers fixed, but since q:child has a namespace declaration, grandchild doesn't need to be fixed, so it does not need to be visited.
    3. Turning off “ancestor may have non-null default namespace declaration”

      In order to make certain namespace operations faster, there is a "state" maintained at XmlDoc nodes that permits a non-null default namespace declaration to occur on an ancestor. This state is fixed up if DeleteTopElement deletes a non-null namespace declaration (as happens in the second “SOAP wrapper removal” example above). The need to set this state is eliminated in descendants of an Element that have a default namespace declaration (either null or not). So, for example:

      <oldTop xmlns="p:uri"> <newTop> <q:child xmlns="q:uri"> <grandchild/> </q:child> </newTop> </p:oldTop>

      The state needs to be fixed at newTop, but since q:child has a default namespace declaration, the state at grandchild does not need to be fixed up, so it does not need to be visited.