Get the corresponding XML nodes with xpath
<p>I have a XML file (actually is a xliff file) where a node has 2 children nodes with identical substructure (which is not known a priori, can be very complex and changes for each <code>&lt;trans-unit&gt;</code>). I'm working with python and lxml library... Example:</p>

<pre><code>&lt;trans-unit id="tu4" xml:space="preserve"&gt;
    &lt;seg-source&gt;
        &lt;mrk mid="0" mtype="seg"&gt;
            &lt;g id="1"&gt;...&lt;/g&gt;
            &lt;g id="2"&gt;...&lt;/g&gt;
            &lt;g id="3"&gt;...&lt;/g&gt;
            &lt;bx id="7"/&gt;...
        &lt;/mrk&gt;
        &lt;mrk mid="1" mtype="seg"&gt;...&lt;/mrk&gt;
        &lt;mrk mid="2" mtype="seg"&gt;...
            &lt;ex id="7"/&gt;
            &lt;g id="8"&gt; FROM HERE &lt;/g&gt;
        &lt;/mrk&gt;
   &lt;/seg-source&gt;
   &lt;target xml:lang="en"&gt;
        &lt;mrk mid="0" mtype="seg"&gt;
            &lt;g id="1"&gt;...&lt;/g&gt;
            &lt;g id="2"&gt;...&lt;/g&gt;
            &lt;g id="3"&gt;...&lt;/g&gt;
            &lt;bx id="7"/&gt;...
        &lt;/mrk&gt;
        &lt;mrk mid="1" mtype="seg"&gt;...&lt;/mrk&gt;
        &lt;mrk mid="2" mtype="seg"&gt;...
            &lt;ex id="7"/&gt;
            &lt;g id="8"&gt; TO HERE &lt;/g&gt;
        &lt;/mrk&gt;
   &lt;/target&gt;
&lt;/trans-unit&gt;
</code></pre>

<p>As you can see, the 2 nodes <code>&lt;seg-source&gt;</code> and <code>&lt;target&gt;</code> have exactly the same sub-structure. My goal is to navigate to each node of <code>&lt;seg-source&gt;</code>, get the text and the tail of that node (and I know how to do that with xpath), translate them and finally (and THIS IS what I don't know how to do) assign to the corresponding node in the <code>&lt;target&gt;</code> the translation...</p>

<p>In other words... suppose I get the node "FROM HERE"... how can I get the node "TO HERE"?. </p>

<p>if you want to pair them all you could just zip the nodes together so you can access the matching codes from each:</p>

<pre><code>from lxml import etree

tree = etree.fromstring(x)
nodes = iter(tree.xpath("//*[self::seg-source or self::target]"))
for seq, tar in zip(nodes, nodes):
    # each node will be the matching nodes from each seq-source and target
    print(seq.xpath(".//*"))
    print(tar.xpath(".//*"))
</code></pre>

<p>Since there are only two in any/each <code>trans-unit</code> you can just use <code>nodes = iter(tree.xpath("//trans-unit/*"))</code> so the names of the nodes inside don't matter.</p>

<pre><code>nodes = iter(tree.xpath("/trans-unit/*"))
for seq, tar in zip(nodes, nodes):
    print(seq.xpath(".//*"))
    print(tar.xpath(".//*"))
</code></pre>

<p>If we run the code on your sample and print each id node you can see the output gets one from each:</p>

<pre><code>In [2]: from lxml import etree

In [3]: tree = etree.fromstring(x)

In [4]: nodes = iter(tree.xpath("//trans-unit/*"))

In [5]: for seq, tar in zip(nodes, nodes):
   ...:         print(seq.xpath(".//g[@id='8']/text()"))
   ...:         print(tar.xpath(".//g[@id='8']/text()"))
   ...:     
[' FROM HERE ']
[' TO HERE ']
</code></pre>

<p>Each node is the corresponding node from each child of trans-unit:</p>

<pre><code>In [7]: for seq, tar in zip(nodes, nodes):
   ...:         print(seq.tag, tar.tag)
   ...:         for n1, n2 in zip(seq.xpath(".//*"),tar.xpath(".//*")):
   ...:                 print(n1.tag, n2.tag)
   ...:         
('seg-source', 'target')
('mrk', 'mrk')
('g', 'g')
('g', 'g')
('g', 'g')
('bx', 'bx')
('mrk', 'mrk')
('mrk', 'mrk')
('ex', 'ex')
('g', 'g')
</code></pre>

python xml xpath lxml xliff