<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="../../../_utils/schema/yaps.rnc" type="application/relax-ng-compact-syntax"?>
<?xml-model href="../../../_utils/schema/yaps.isosch" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<?xml-stylesheet type="text/xsl" href="yaps2slidy1.xslt"?>
<!-- $Id: tree_navigation.xml 51709 2026-05-28 23:29:13Z syd $ -->
<TEI xmlns="http://www.wwp.northeastern.edu/ns/yaps" version="5.0">
  <teiHeader>
    <fileDesc>
      <titleStmt>
        <title>Navigating the XML Tree</title>
        <author>Syd Bauman</author>
      </titleStmt>
      <editionStmt>
        <edition>TEI Summer School, University of Graz, Fri, 13 Sep 19</edition>
      </editionStmt>
      <publicationStmt>
        <distributor>Women Writers Project (via website)</distributor>
        <address>
          <addrLine>url:mailto:wwp@northeastern.edu</addrLine>
        </address>
        <date when="2019-09-13"/>
        <availability status="restricted">
          <p>Copyright 2018 Syd Bauman and the Women Writers Project</p>
          <p>This TEI-encoded XML file is available under the terms of
          the <ref target="http://creativecommons.org/licenses/by-sa/3.0/">Creative
          Commons Attribution-ShareAlike 3.0 (Unported)</ref>
          license.</p>
        </availability>
        <pubPlace>Boston, MA  USA</pubPlace>
      </publicationStmt>
      <sourceDesc>
        <p>Brief review of essential XML; XPath path expressions.</p>
      </sourceDesc>
    </fileDesc>
    <revisionDesc>
      <change who="#sbauman.emt" when="2018-09-09">Created, based on xml_and_xpath</change>
    </revisionDesc>
  </teiHeader>
  <text>
    <presentation>

      <section>
        <head>XML representations</head>
        <slide>
          <table>
            <row>
              <cell style="vertical-align: top;">
                <egMarkup scheme="ad-hoc" type="valid" xmldecl="true">
                  <book>
                    <introduction>Blah blah blah ... </introduction>
                    <chapter>
                      <heading>Wines</heading>
                      <section>White wines ... </section>
                      <section>Red wines ... </section>
                    </chapter>
                    <chapter>
                      <heading>Beers</heading>
                      <section>Ales ... </section>
                      <section>Lagers ... </section>
                    </chapter>
                    <index> stuff ... </index>
                  </book>
                </egMarkup>
              </cell>
              <cell style="padding: 0ex 1ex 1ex 1ex; vertical-align: top;">
                <figure>
                  <graphic url="../../../_utils/gfx/boxes_book2.png" width="100%"/>
                  <figDesc>Classic boxes-inside-boxes representation
                  of a mythical book that contains an introduction,
                  two chapters, and an index, where each chapter
                  contains a heading and two sections</figDesc>
                </figure>
              </cell>
              <cell style="vertical-align: top;">
                <figure>
                  <graphic url="../../../_utils/gfx/tree_book1.png" width="100%"/>
                  <figDesc>Classic tree representation of a mythical
                  book that contains an introduction, two chapters,
                  and an index, where each chapter contains a heading
                  and two sections</figDesc>
                </figure>
              </cell>
            </row>
          </table>
        </slide>
      </section>

      <section>
        <head>Sample text</head>
        <slide>
          <eg><![CDATA[    ]]><hi rend="class(interest)">Warp Speed, Ms Bright!</hi><![CDATA[
There was a young lady named Bright,
Who travelled much faster than light,
She departed one day,
In a relative way,
And returned on the previous night.]]></eg>
        </slide>
      </section>
      
      <section>
        <head>Sample Document Instance</head>
        <slide>
          <egMarkup scheme="TEI" type="valid" xmldecl="true">
            <lg type="limerick" rhyme="aabba" n="3">
              <head>Warp Speed, Ms Bright!</head>
              <l>There was a young lady named <rhyme label="a">Bright</rhyme>,</l>
              <l>Who travelled much faster than <rhyme label="a">light</rhyme>,</l>
              <l>She departed one <rhyme label="b">day</rhyme>,</l>
              <l>In a <term xml:id="t17">relative</term> way <rhyme label="b">way</rhyme>,</l>
              <l>And returned on the previous <rhyme label="a">night</rhyme>.</l>
              <note target="#t17">See
              <ptr target="http://en.wikipedia.org/wiki/Theory_of_relativity"/>.</note>
            </lg>
          </egMarkup>
        </slide>
      </section>
      
      <section>
        <head>Sample Portion of TEI Tree</head>
        <slide>
          <p>Here is a graphic representation of the grossly simplified tree representation of the previos TEI
          sub-document. (It is not a full TEI document, as it does not have a <gi>teiHeader</gi>.)</p>
          <figure>
            <graphic url="../../../_utils/gfx/tree_limerick1.png"/>
            <figDesc>Classic simplified tree diagram of the limerick
            <title>Warp Speed, Ms Bright!</title> that uses a dashed
            curved arrow to represent the link from the <gi>note</gi>
            to the <gi>term</gi>, and a dotted arror to indicate the
            link from the <gi>ptr</gi> to the Wikipedia article.</figDesc>
          </figure>
        </slide>
      </section>

      <sectionGrp>
        <head>Walking the Tree</head>
        <section>
          <head>tree (with <code>self::</code>)</head>
          <slide>
            <figure>
              <graphic url="../../../_utils/gfx/xpath_axis_self.png"/>
              <figDesc>Classic tree diagram of generic XML document,
              elements only, with /*[1]/*[2]/*[2]/*[3]
              highlighted.</figDesc>
            </figure>
          </slide>
        </section>
        <section>
          <head>descendants (<code>child::</code> and <code>descendant::</code>)</head>
          <slide>
            <figure>
              <graphic url="../../../_utils/gfx/xpath_axis_descendant.png"/>
              <figDesc>Classic tree diagram of generic XML document,
              elements only, with /*[1]/*[2]/*[2]/*[3] highlighted,
              all its children marked in green, and all its
              descendants (including the children) surrounded with a
              green circle.</figDesc>
            </figure>
          </slide>
        </section>
        <section>
          <head>ancestors (<code>parent::</code> and <code>ancestor::</code>)</head>
          <slide>
            <figure>
              <graphic url="../../../_utils/gfx/xpath_axis_ancestor.png"/>
              <figDesc>Classic tree diagram of generic XML document,
              elements only, with /*[1]/*[2]/*[2]/*[3] highlighted,
              its parent marked in purple, and all its
              ancestors (including the parent) surrounded with a
              purple circle.</figDesc>
            </figure>
          </slide>
        </section>
        <section>
          <head>preceding (<code>preceding::</code> and <code>preceding-sibling::</code>)</head>
          <slide>
            <figure>
              <graphic url="../../../_utils/gfx/xpath_axis_preceding.png"/>
              <figDesc>Classic tree diagram of generic XML document,
              elements only, with /*[1]/*[2]/*[2]/*[3] highlighted,
              its preceding siblings marked in red, and all its
              preceding elements (including the preceding siblings)
              surrounded with a red circle.</figDesc>
            </figure>
          </slide>
        </section>
        <section>
          <head>following (<code>following::</code> and <code>following-sibling::</code>)</head>
          <slide>
            <figure>
              <graphic url="../../../_utils/gfx/xpath_axis_following.png"/>
              <figDesc>Classic tree diagram of generic XML document,
              elements only, with /*[1]/*[2]/*[2]/*[3] highlighted,
              its following sibling marked in blue, and all its
              following elements (including the following sibling)
              surrounded with a blue circle.</figDesc>
            </figure>
          </slide>
        </section>
        <section>
          <head>axes <code>:-)</code></head>
          <slide>
            <figure>
              <graphic url="../../../_utils/gfx/xpath_axes.png"/>
              <figDesc>Combination of above 4</figDesc>
            </figure>
          </slide>
        </section>
      </sectionGrp>
      
      <section>
        <head>XPath …</head>
        <slide>
          <p>… lets us (among other things) select nodes in the tree.</p>
          <p>… is used by XSLT, XQuery, Schematron; XLink and XPointer, too.</p>
        </slide>
      </section>

      <section>
        <head>basic filepath-like path expressions</head>
        <slide>
          <p>A bare-bones path expression is similar to filesystem
          addressing: if the path starts with a solidus
          (<mentioned>/</mentioned> aka <soCalled>forward
          slash</soCalled>), then it represents a path from the root;
          if it does not start with a solidus then it represents a
          path from <q>here</q>.</p>
          <eg style="font-size: larger;">/TEI/teiHeader/fileDesc/titleStmt/title</eg>
          <eg style="font-size: larger;">list/item/label</eg>
        </slide>
      </section>

      <section>
        <head>Try it!</head>
        <slide>
          <p>In oXygen open the file <name
          type="file"><ref target="../../demos/xslt_intro/ham.xml">ham.xml</ref></name>.
          In the upper L corner there is
          a text-entry field (looks like a search box). Ensure the box
          is labelled <mentioned>XPath 2.0</mentioned> (or
          <mentioned>XPath 3.0</mentioned>). Then type in
          <code>/TEI/teiHeader/fileDesc/titleStmt/author</code>.
          Notice that you have content completion, so it is very easy
          to type. (If you don’t, set it in <code>Options /
          Preferences ; Editor / Content Completion /
          XPath</code>.)</p>
          <figure>
            <head>oXygen XPath console</head>
            <figDesc>An image of an oXygen window</figDesc>
            <graphic url="../../../_utils/gfx/oxygen_xpath_screen_shot_01.png" width="70%"/>
          </figure>
          <p>Here is what the <ref target="https://www.oxygenxml.com/doc/versions/21.1/ug-editor/topics/xpath-toolbar.html">oXygen
          XPath toolbar</ref> (or <mentioned>console</mentioned>) will look like.</p>
        </slide>
      </section>

      <section>
        <head>XPath basics</head>
        <slide>
          <list>
            <item>steps are separated by slashes (<mentioned>/</mentioned>,
            aka <soCalled>solidus</soCalled>)</item>
            <item>the default axis (i.e., direction) is <code>child::</code>
            <list>
              <item>thus <code>/duck</code> and <code>/child::duck</code> are equivalent</item>
            </list></item>
            <item>to use a different axis, specify it with two colons, e.g. <code>preceding-sibling::item</code></item>
            <item>each step selects 0 or more <term>nodes</term>, in this case elements, and
            hands them on to the next step
            <list>
              <item>a step can address attributes, comments, processing instructions, or 
              text nodes, too — we’ll start with elements for now, though</item>
            </list></item>
            <item>the nodes an XPath returns are specified by the last step
            <list>
              <item><code>moose/calf</code> returns all the <gi>calf</gi> elements
              that are children of a <gi>moose</gi> element</item>
              <item><code>calf/parent::moose</code> returns all the <gi>moose</gi>
              elements that are the parent of a <gi>calf</gi> element (unlike
              with real moose, each <gi>calf</gi> has only one parent <gi>moose</gi>)</item>
            </list>
            </item>
          </list>
        </slide>
      </section>
      
      <section>
        <head>XPath axes: me, my descendants, and my ancestors</head>
        <slide>
          <table rend="class( bordered )">
            <row role="label" rend="class( label )">
              <cell>short</cell>
              <cell>long</cell>
              <cell>means</cell>
              <cell>try it!</cell>
            </row>
            <row>
              <!-- XPath 2.0 says that "." is the ContextItemExpr (production 47) -->
              <!-- It may be a node or an atomic value; thus self::node() is the -->
              <!-- same iff the context item is a node. -->
              <cell><code style="font-weight:bold;">.</code></cell>
              <cell><code>self::node()</code></cell>
              <cell>me, whatever I happen to be (element, attribute, comment, processing instruction, document root, or even text) <hi rend="class(dull)">(note: long and short are not exactly equivalent)</hi></cell>
              <cell rend="class(dull)">oXygen shows node cursor is in
              <lb/>Note: if you turn on <code>XPath update on cursor move</code>, oXygen
              will show an XPath to the cursor in the XPath toolbar</cell>
            </row>
            <row>
              <cell><code>said</code></cell>
              <cell><code>child::said</code></cell>
              <cell>my <gi>said</gi> children</cell>
              <cell>in this encoding there is 1 <gi>div</gi> for each <val>act</val>,
              each of
              which holds 1 <gi>div</gi> for each <val>scene</val>;
              list all the <gi>head</gi> elements for the scenes.
              <!-- /TEI/text/body/div/div/head --></cell>
            </row>
            <row>
              <cell><code>*</code></cell>
              <cell><code>child::*</code></cell>
              <cell>all my element children</cell>
              <cell>list all children of <gi>sourceDesc</gi></cell>
              <!-- /TEI/teiHeader/fileDesc/titleStmt/sourceDesc/* -->
            </row>
            <row>
              <cell><code>//div</code></cell>
              <cell><code>descendant::div</code></cell>
              <!-- //div == /descendant-or-self::node()/child::div -->
              <!-- Thus //div[1] != /descendant::div[1] -->
              <!-- //div[1] means "get me every <div> that is a first child" -->
              <!-- /descendant::div[1] means "get me first <div> in doc" -->
              <cell>my <gi>div</gi> descendants <hi rend="class(dull)">(note: long and short are not exactly equivalent)</hi></cell>
              <cell>list all stage directions (<gi>stage</gi>)</cell>
              <!-- /TEI/text//stage <hi rend="class(dull)">note output order</hi> -->
            </row>
            <row>
              <cell><code style="font-weight:bold;">..</code></cell>
              <cell><code>parent::node()</code></cell>
              <cell>my parent, whatever it happens to be (element or root)</cell>
              <cell>list the parents of stage directions</cell>
              <!-- /TEI/text//stage/.. -->
            </row>
            <row>
              <cell rend="class(dull)">[none]</cell>
              <cell><code>parent::author</code></cell>
              <cell>my parent, if it is an <gi>author</gi></cell>
              <cell>list the speech (<gi>sp</gi>) parents of stage directions</cell>
              <!-- /TEI/text//stage/parent::sp -->
            </row>
            <row>
              <cell rend="class(dull)">[none]</cell>
              <cell><code>ancestor::div</code></cell>
              <cell>my <gi>div</gi> ancestors</cell>
              <cell>list all the headings of the <gi>div</gi> ancestors of the famous <q>To be, or not to be</q> (which you can find by searching for it)</cell>
              <!-- ./ancestor::div/head -->
            </row>
            <row>
              <cell rend="class(dull)">[none]</cell>
              <cell><code>ancestor::*</code></cell>
              <cell>all my ancestors</cell>
              <cell>list the ancestors of the <gi>author</gi> element(s)</cell>
              <!-- /TEI/teiHeader/fileDesc/titleStmt/author/ancestor::* -->
              <!-- Note that only 1 set of ancestors is returned -->
            </row>
          </table>
          <p><bibl>Kay, chapter 9</bibl></p>
        </slide>
      </section>

      <section>
        <head>XPath axes: following, preceding, and attributes</head>
        <slide>
          <table rend="class( bordered )">
            <row role="label" rend="class( label )">
              <cell>short</cell>
              <cell>long</cell>
              <cell>means</cell>
              <cell>try it!</cell>
            </row>
            <row>
              <cell rend="class(dull)">[none]</cell>
              <cell><code>following::item</code></cell>
              <cell>all the <gi>item</gi>s that come after me</cell>
              <cell>find all the <gi>title</gi> elements that occur <emph>after</emph> the <gi>titleStmt</gi></cell>
              <!-- /TEI/teiHeader/fileDesc/titleStmt/following::title -->
            </row>
            <row>
              <cell rend="class(dull)">[none]</cell>
              <cell><code>following-sibling::l</code></cell>
              <cell>the <gi>l</gi> children of my parent that come after me (i.e., the rest of the stanza)</cell>
              <cell>find all the children of <gi>titleStmt</gi> that follow <gi>author</gi></cell>
              <!-- //titleStmt/author/following-sibling::* -->
            </row>
            <row>
              <cell rend="class(dull)">[none]</cell>
              <cell><code>preceding::pb</code></cell>
              <cell>the <gi>pb</gi>s that come before me</cell>
              <cell>find all the <gi>p</gi> elements that occur before <q>To be, or not to be:</q></cell>
              <!-- ./preceding::p -->
            </row>
            <row>
              <cell rend="class(dull)">[none]</cell>
              <cell><code>preceding-sibling::head</code></cell>
              <cell>the <gi>head</gi> children of my parent that come before me</cell>
              <cell>do any elements ever occur before the <gi>speaker</gi> within a speech?</cell>
              <!-- //sp/speaker/preceding-sibling::* -->
              <!-- //sp/*/following-sibling::speaker -->
            </row>
            <row>
              <cell><code>@rend</code></cell>
              <cell><code>attribute::rend</code></cell>
              <cell>my <att>rend</att> attribute</cell>
              <cell>list all the <att>who</att> attributes</cell>
              <!-- //@who -->
            </row>
            <row>
              <cell><code>@*</code></cell>
              <cell><code>attribute::*</code></cell>
              <cell>all of my attributes</cell>
              <cell>do any of the <gi>choice</gi> elements have attributes at all?</cell>
              <!-- //stage/@* -->
            </row>
          </table>
          <p><bibl>Kay, chapter 9</bibl></p>
        </slide>
      </section>

      <section>
        <head>Don’t want them all?</head>
        <slide>
          <list type="incremental">
            <item>Many of the above XPaths return multiple nodes
            — what if you only want a particular one?</item>
            <item>If you only want Act 3, Scene 1:
            <eg style="font-size: larger;">/TEI/text/body/div[3]/div[1]></eg></item>
            <item>Works well presuming you
            know what you want by element count.</item>
            <item>But in many cases,
            that is at least inconvenient, if not outright unknown.</item>
            <item>No matter how many <gi>div</gi>s there are, we know this
            particular scene has an <att>xml:id</att> of <val>sha-ham301</val>. Thus:
            <eg style="font-size: larger;">//div[ @xml:id eq 'sha-ham301']</eg>
            selects the same node (as would <code>//*[ @xml:id eq 'sha-ham301']</code>)
            </item>
          </list>
        </slide>
      </section>

      <section>
        <head>predicates</head>
        <slide>
          <p>An XPath <term>predicate</term> filters the nodes
          retrieved by a given step</p>
          <p>Predicates are expressed after the node test in square
          brackets</p>
          <p>The following are based on
          <!-- <ref target="https://www.wwp.northeastern.edu/outreach/seminars/xpath_2019-09_tei/demos/xslt_intro/places.xml">https://www.wwp.northeastern.edu/outreach/seminars/xpath_2019-09_tei/demos/xslt_intro/places.xml</ref>, -->
          <ref target="../../demos/xslt_intro/places.xml">../../demos/xslt_intro/places.xml</ref>,
          <!-- <ref target="http://paramedic.wwp.northeastern.edu/~syd/WWPweb/outreach/seminars/xpath_2019-09_tei/demos/xslt_intro/places.xml">http://paramedic.wwp.northeastern.edu/~syd/WWPweb/outreach/seminars/xpath_2019-09_tei/demos/xslt_intro/places.xml</ref>, -->
          which you can open in oXygen with <code>File &gt; Open URL…</code> or
          <code>⌘-u</code> (Mac) or <code>ctl-u</code> (Windows), and
          then pasting in the URL.</p>
          <table rend="class( bordered )">
            <row role="label" rend="class( label )">
              <cell>XPath</cell>
              <cell>selects</cell>
            </row>
            <row>
              <cell><code>//listPlace/place[1]</code></cell>
              <cell>the ﬁrst <gi>place</gi> of each <gi>listPlace</gi> (of which there only happens to be one)</cell>
            </row>
            <row>
              <cell><code>//*[@cRef]</code></cell>
              <cell>all elements that have a <att>cRef</att> attribute</cell>
            </row>
            <row>
              <cell><code>//title[ @level eq 'm']</code></cell>
              <cell>all monographic titles</cell>
            </row>
            <row>
              <cell><code>/TEI/text//name[ not( @key ) ]</code></cell>
              <cell><gi>name</gi> elements that are missing their <att>key</att> attributes</cell>
            </row>
            <row>
              <cell><code>//lg[@type='song']/l[1]</code></cell>
              <cell>list ﬁrst line of each song (16 nodes)</cell>
            </row>
            <row>
              <cell><code>(//lg[@type='song']/l)[1]</code></cell>
              <cell>returns ﬁrst line of all songs (1 node)</cell>
            </row>
          </table>
        </slide>
      </section>

      <section>
        <head>Repeat Sample Document Instance</head>
        <slide>
          <egMarkup scheme="TEI" type="valid" xmldecl="true">
            <lg type="limerick" rhyme="aabba" n="3">
              <head>Warp Speed, Ms Bright!</head>
              <l>There was a young lady named <rhyme label="a">Bright</rhyme>,</l>
              <l>Who travelled much faster than <rhyme label="a">light</rhyme>,</l>
              <l>She departed one <rhyme label="b">day</rhyme>,</l>
              <l>In a <term xml:id="t17">relative</term> way <rhyme label="b">way</rhyme>,</l>
              <l>And returned on the previous <rhyme label="a">night</rhyme>.</l>
              <note target="#t17">See
              <ptr target="http://en.wikipedia.org/wiki/Theory_of_relativity"/>.</note>
            </lg>
          </egMarkup>
        </slide>
      </section>

      <section>
        <head>XSLT View</head>
        <slide>
          <p>Same document, but adding text and attribute nodes</p>
          <figure>
            <graphic url="../../../_utils/gfx/tree_limerick_detail1.png"/>
            <figDesc>Tree diagram of the limerick <title>Warp Speed,
            Ms Bright!</title> that has element, attribute, and text
            nodes <emph>except for whitespace-only text
            nodes</emph>.</figDesc>
          </figure>
          <p>Element nodes have just the element’s local name;
          attribute nodes have just the name of the attribute; text
          nodes have just the word <mentioned>text</mentioned>.</p>
        </slide>
      </section>

    </presentation>
  </text>
</TEI>
