Search code examples
pythonpython-3.xxmlbeautifulsouptei

Extract a text with python beautifulsoup from a TEI XML document


I'm trying to extract a text from a TEI XML document, I can't figure out how to get the other tags names not just the text itself.

   <text>
      <body>
         <div xml:id="S00483.1">
            <div xml:id="S00483.1.1">
               <pb xml:id="S00483.1v" n="1v"/>
               <cb xml:id="S00483.1vA" n="1vA"/>
               <lb n="1"/>
               <div xml:id="S00483.1.1.1">
                  <ab xml:id="S00483.1.1.1.1">
                     <w xml:id="S00483.1.1.1.1.1">מאמתי</w>
                     <w xml:id="S00483.1.1.1.1.2">קורין</w>
                     <w xml:id="S00483.1.1.1.1.3">את</w>
                     <w xml:id="S00483.1.1.1.1.4">שמע</w>
                     <w xml:id="S00483.1.1.1.1.5">בערבים</w>
                     <w xml:id="S00483.1.1.1.1.6">משעה</w>
                     <w xml:id="S00483.1.1.1.1.7">שהכהנים</w>
                     <lb n="2"/>
                     <w xml:id="S00483.1.1.1.1.8">נכנסין</w>
                     <w xml:id="S00483.1.1.1.1.9">לאכל</w>
                     <w xml:id="S00483.1.1.1.1.10">בתרומתן</w>
                     <w xml:id="S00483.1.1.1.1.11">עד</w>
                     <w xml:id="S00483.1.1.1.1.12">סוף</w>
                     <w xml:id="S00483.1.1.1.1.13">האשמורת</w>
                     <lb n="3"/>
                     <w xml:id="S00483.1.1.1.1.14">הראשנה</w>
                     <w xml:id="S00483.1.1.1.1.15">דברי</w>
                     <w xml:id="S00483.1.1.1.1.16">רבי</w>
                     <w xml:id="S00483.1.1.1.1.17">אליעזר</w>
                     <w xml:id="S00483.1.1.1.1.18">וחכמין</w>
                     <w xml:id="S00483.1.1.1.1.19">אומרין</w>
                     <w xml:id="S00483.1.1.1.1.20">עד</w>
                     <lb n="4"/>
                     <w xml:id="S00483.1.1.1.1.21">חצות</w>
                     <w xml:id="S00483.1.1.1.1.22">רבן</w>
                     <w xml:id="S00483.1.1.1.1.23">גמליאל</w>
                     <w xml:id="S00483.1.1.1.1.24">אומר</w>
                     <w xml:id="S00483.1.1.1.1.25">עד</w>
                     <w xml:id="S00483.1.1.1.1.26">שיעלה</w>
                     <w xml:id="S00483.1.1.1.1.27">עמוד</w>
                     <lb n="5"/>
                     <w xml:id="S00483.1.1.1.1.28">השחר</w>
                     <pc type="unitEnd" rend="null"/>
                     <milestone unit="MSMishnah" n="2"/>
                     <label>ב<am rend="null">׳</am>
                     </label>
                     <w xml:id="S00483.1.1.1.1.29">מעשה</w>
                     <w xml:id="S00483.1.1.1.1.30">שבאו</w>
                     <w xml:id="S00483.1.1.1.1.31">בניו</w>
                     <w xml:id="S00483.1.1.1.1.32">מבית</w>
                     <w xml:id="S00483.1.1.1.1.33">המשתה</w>
                     <lb n="6"/>
                     <w xml:id="S00483.1.1.1.1.34">אמרו</w>
                     <w xml:id="S00483.1.1.1.1.35">לו</w>
                     <w xml:id="S00483.1.1.1.1.36">לא</w>
                     <w xml:id="S00483.1.1.1.1.37">קרינו</w>
                     <w xml:id="S00483.1.1.1.1.38">את</w>
                     <w xml:id="S00483.1.1.1.1.39">שמע</w>
                     <w xml:id="S00483.1.1.1.1.40">אמר</w>
                     <w xml:id="S00483.1.1.1.1.41">להם</w>
                     <w xml:id="S00483.1.1.1.1.42">אם</w>
                     <w xml:id="S00483.1.1.1.1.43">לא</w>
                     <lb n="7"/>
                     <w xml:id="S00483.1.1.1.1.44">עלה</w>
                     <w xml:id="S00483.1.1.1.1.45">עמוד</w>
                     <w xml:id="S00483.1.1.1.1.46">השחר</w>
                     <w xml:id="S00483.1.1.1.1.47">מותרין</w>
                     <w xml:id="S00483.1.1.1.1.48">אתם</w>
                     <w xml:id="S00483.1.1.1.1.49">לקרות</w>
                     <pc type="unitEnd" rend="null"/>
                     <milestone unit="MSMishnah" n="3"/>
                     <label>ג<am rend="null">׳</am>
                     </label>
                     <w xml:id="S00483.1.1.1.1.50">ולא</w>
                     <lb n="8"/>
                     <w xml:id="S00483.1.1.1.1.51">זו</w>
                     <w xml:id="S00483.1.1.1.1.52">בלבד</w>
                     <w xml:id="S00483.1.1.1.1.53">אלא</w>
                     <w xml:id="S00483.1.1.1.1.54">כל</w>
                     <w xml:id="S00483.1.1.1.1.55">שאמרו</w>
                     <w xml:id="S00483.1.1.1.1.56">חכמים</w>
                     <w xml:id="S00483.1.1.1.1.57">עד</w>
                     <w xml:id="S00483.1.1.1.1.58">חצות</w>
                     <surplus reason="fill">מצ<am rend="null">׳</am>
                     </surplus>
                     <lb n="9"/>
                     <w xml:id="S00483.1.1.1.1.59">מצותן</w>
                     <w xml:id="S00483.1.1.1.1.60">עד</w>
                     <w xml:id="S00483.1.1.1.1.61">שיעלה</w>
                     <w xml:id="S00483.1.1.1.1.62">עמוד</w>
                     <w xml:id="S00483.1.1.1.1.63">השחר</w>
                     <pc type="unitEnd" rend="null"/>
                     <milestone unit="MSMishnah" n="4"/>
                     <label>ד<am rend="null">׳</am>
                     </label>
                     <w xml:id="S00483.1.1.1.1.64">הקטר</w>
                     <lb n="10"/>
                     <w xml:id="S00483.1.1.1.1.65">חלבים</w>
                     <w xml:id="S00483.1.1.1.1.66">ואיברין</w>
                     <delSpan spanTo="#d1e217" hand="#h2" rend="deletion-mark"/>
                     <w xml:id="S00483.1.1.1.1.67">ואכילת</w>
                     <w xml:id="S00483.1.1.1.1.68">פסחים</w>
                     <anchor xml:id="d1e217" type="del"/>
                     <w xml:id="S00483.1.1.1.1.69">מצותן</w>
                     <w xml:id="S00483.1.1.1.1.70">עד</w>
                     <lb n="11"/>
                     <w xml:id="S00483.1.1.1.1.71">שיעלה</w>
                     <w xml:id="S00483.1.1.1.1.72">עמוד</w>
                     <w xml:id="S00483.1.1.1.1.73">השחר</w>
                     <pc type="unitEnd" rend="null"/>
                     <milestone unit="MSMishnah" n="5"/>
                     <label>ה<am rend="null">׳</am>
                     </label>
                     <w xml:id="S00483.1.1.1.1.74">וכל</w>
                     <w xml:id="S00483.1.1.1.1.75">הנאכלין</w>
                     <w xml:id="S00483.1.1.1.1.76">ליום</w>
                     <lb n="12"/>
                     <w xml:id="S00483.1.1.1.1.77">אחד</w>
                     <w xml:id="S00483.1.1.1.1.78">מצותן</w>
                     <w xml:id="S00483.1.1.1.1.79">עד</w>
                     <w xml:id="S00483.1.1.1.1.80">שיעלה</w>
                     <w xml:id="S00483.1.1.1.1.81">עמוד</w>
                     <w xml:id="S00483.1.1.1.1.82">השחר</w>
                     <w xml:id="S00483.1.1.1.1.83">אם</w>
                     <w xml:id="S00483.1.1.1.1.84">כן</w>
                     <lb n="13"/>
                     <w xml:id="S00483.1.1.1.1.85">למה</w>
                     <w xml:id="S00483.1.1.1.1.86">אמרו</w>
                     <w xml:id="S00483.1.1.1.1.87">חכמים</w>
                     <w xml:id="S00483.1.1.1.1.88">עד</w>
                     <w xml:id="S00483.1.1.1.1.89">חצות</w>
                     <w xml:id="S00483.1.1.1.1.90">אלא</w>
                     <w xml:id="S00483.1.1.1.1.91">להרחיק</w>
                     <w xml:id="S00483.1.1.1.1.92">את</w>
                     <lb n="14"/>
                     <w xml:id="S00483.1.1.1.1.93">האדם</w>
                     <w xml:id="S00483.1.1.1.1.94">מן</w>
                     <w xml:id="S00483.1.1.1.1.95">העבירה</w>
                     <pc type="unitEnd" rend="null"/>
                  </ab>
                  <ab xml:id="S00483.1.1.1.2">

The desired output:

S00483.1.1.1.1 מאמתי קורין את שמע בערבים משעה שהכהנים נכנסין לאכל בתרומתן עד סוף האשמורת הראשנה דברי רבי אליעזר וחכמין אומרין עד חצות רבן גמליאל אומר עד שיעלה עמוד השחר מעשה שבאו בניו מבית המשתה אמרו לו לא קרינו את שמע אמר להם אם לא עלה עמוד השחר מותרין אתם לקרות ולא זו בלבד אלא כל שאמרו חכמים עד חצות מצותן עד שיעלה עמוד השחר הקטר חלבים ואיברין ואכילת פסחים מצותן עד שיעלה עמוד השחר וכל הנאכלין ליום אחד מצותן עד שיעלה עמוד השחר אם כן למה אמרו חכמים עד חצות אלא להרחיק את האדם מן העבירה
S00483.1.1.1.2 מאמתי קורין את שמע בשחרים משיכירו בין תכלת ללבן רבי אליעזר אומר בין תכלת לכרתן וגומרה עד הנץ החמה יהושע עד שלש שעות שכן דרך בני מלכים לעמוד בשלש שעות הקורא מיכן והלך לא הפסיד כאדם שהוא קורא בתורה
S00483.1.1.1.3 בית שמי אומרין בערב כל אדם יטו ויקרו ובבקר יעמודו ובשכבך ובקומך ובית הלל כל אדם קורין כדרכן ובלכתך בדרך אם כן למה נאמר בשכבך ובקומך אלא בשעה שדרך בני אדם שוכבין ובשעה שדרך בני אדם עומדין אמר טרפון אני הייתי בא בדרך והטיתי לקרות כדברי בית שמי וסיכנתי בעצמי מפני הלסטים אמרו לו כדיי הייתה לחוב בעצמך שעברתה על דברי בית הלל

What I get so far:

מאמתי קורין את שמע בערבים משעה שהכהנים נכנסין לאכל בתרומתן עד סוף האשמורת הראשנה דברי רבי אליעזר וחכמין אומרין עד חצות רבן גמליאל אומר עד שיעלה עמוד השחר מעשה שבאו בניו מבית המשתה אמרו לו לא קרינו את שמע אמר להם אם לא עלה עמוד השחר מותרין אתם לקרות ולא זו בלבד אלא כל שאמרו חכמים עד חצות מצותן עד שיעלה עמוד השחר הקטר חלבים ואיברין ואכילת פסחים מצותן עד שיעלה עמוד השחר וכל הנאכלין ליום אחד מצותן עד שיעלה עמוד השחר אם כן למה אמרו חכמים עד חצות אלא להרחיק את האדם מן העבירה
מאמתי קורין את שמע בשחרים משיכירו בין תכלת ללבן רבי אליעזר אומר בין תכלת לכרתן וגומרה עד הנץ החמה
                         יהושע
                         עד שלש שעות שכן דרך בני מלכים לעמוד בשלש שעות הקורא מיכן והלך לא הפסיד כאדם שהוא קורא בתורה
בית שמי אומרין בערב כל אדם יטו ויקרו ובבקר יעמודו
                         ובשכבך ובקומך ובית הלל
                         כל אדם קורין כדרכן
                         ובלכתך בדרך אם כן למה נאמר בשכבך ובקומך אלא בשעה שדרך בני אדם שוכבין ובשעה שדרך בני אדם עומדין אמר
                         טרפון אני הייתי בא בדרך והטיתי לקרות כדברי בית שמי וסיכנתי בעצמי מפני הלסטים אמרו לו כדיי הייתה לחוב בעצמך שעברתה על דברי בית הלל

My code:

from lxml import etree # This is the only part of lxml we need
import pandas as pd #
from collections import Counter # A built-in tool for counting items

# First create a parser object. It will work faster if you tell it not to collect IDs.
parser = etree.XMLParser(collect_ids=False)

# Parse your XML file into a "tree" object
tree = etree.parse('S00483.xml', parser)

# Get the XML from the tree object
parma = tree.getroot()

# Create your nsmap for the 'tei' namespace
# You only need to do this once in your script,
# but you'll refer back to this variable throughout
# the rest of this notebook.
nsmap={'tei': 'http://www.tei-c.org/ns/1.0'}

all_line_tags = parma.findall(".//tei:ab", namespaces=nsmap)

for line in all_line_tags[:10]: #Only the first 20 lines
    print(' '.join([w.text for w in line.findall(".//tei:w", namespaces=nsmap)]))

Solution

  • You can try (but I'm not sure if the text direction left-to-rigth is correct):

    from bs4 import BeautifulSoup
    
    xml_text = """\
       <text>
          <body>
             <div xml:id="S00483.1">
                <div xml:id="S00483.1.1">
                   <pb xml:id="S00483.1v" n="1v"/>
                   <cb xml:id="S00483.1vA" n="1vA"/>
                   <lb n="1"/>
                   <div xml:id="S00483.1.1.1">
                      <ab xml:id="S00483.1.1.1.1">
                         <w xml:id="S00483.1.1.1.1.1">מאמתי</w>
                         <w xml:id="S00483.1.1.1.1.2">קורין</w>
                         <w xml:id="S00483.1.1.1.1.3">את</w>
                         <w xml:id="S00483.1.1.1.1.4">שמע</w>
                         <w xml:id="S00483.1.1.1.1.5">בערבים</w>
                         <w xml:id="S00483.1.1.1.1.6">משעה</w>
                         <w xml:id="S00483.1.1.1.1.7">שהכהנים</w>
                         <lb n="2"/>
                         <w xml:id="S00483.1.1.1.1.8">נכנסין</w>
                         <w xml:id="S00483.1.1.1.1.9">לאכל</w>
                         <w xml:id="S00483.1.1.1.1.10">בתרומתן</w>
                         <w xml:id="S00483.1.1.1.1.11">עד</w>
                         <w xml:id="S00483.1.1.1.1.12">סוף</w>
                         <w xml:id="S00483.1.1.1.1.13">האשמורת</w>
                         <lb n="3"/>
                         <w xml:id="S00483.1.1.1.1.14">הראשנה</w>
                         <w xml:id="S00483.1.1.1.1.15">דברי</w>
                         <w xml:id="S00483.1.1.1.1.16">רבי</w>
                         <w xml:id="S00483.1.1.1.1.17">אליעזר</w>
                         <w xml:id="S00483.1.1.1.1.18">וחכמין</w>
                         <w xml:id="S00483.1.1.1.1.19">אומרין</w>
                         <w xml:id="S00483.1.1.1.1.20">עד</w>
                         <lb n="4"/>
                         <w xml:id="S00483.1.1.1.1.21">חצות</w>
                         <w xml:id="S00483.1.1.1.1.22">רבן</w>
                         <w xml:id="S00483.1.1.1.1.23">גמליאל</w>
                         <w xml:id="S00483.1.1.1.1.24">אומר</w>
                         <w xml:id="S00483.1.1.1.1.25">עד</w>
                         <w xml:id="S00483.1.1.1.1.26">שיעלה</w>
                         <w xml:id="S00483.1.1.1.1.27">עמוד</w>
                         <lb n="5"/>
                         <w xml:id="S00483.1.1.1.1.28">השחר</w>
                         <pc type="unitEnd" rend="null"/>
                         <milestone unit="MSMishnah" n="2"/>
                         <label>ב<am rend="null">׳</am>
                         </label>
                         <w xml:id="S00483.1.1.1.1.29">מעשה</w>
                         <w xml:id="S00483.1.1.1.1.30">שבאו</w>
                         <w xml:id="S00483.1.1.1.1.31">בניו</w>
                         <w xml:id="S00483.1.1.1.1.32">מבית</w>
                         <w xml:id="S00483.1.1.1.1.33">המשתה</w>
                         <lb n="6"/>
                         <w xml:id="S00483.1.1.1.1.34">אמרו</w>
                         <w xml:id="S00483.1.1.1.1.35">לו</w>
                         <w xml:id="S00483.1.1.1.1.36">לא</w>
                         <w xml:id="S00483.1.1.1.1.37">קרינו</w>
                         <w xml:id="S00483.1.1.1.1.38">את</w>
                         <w xml:id="S00483.1.1.1.1.39">שמע</w>
                         <w xml:id="S00483.1.1.1.1.40">אמר</w>
                         <w xml:id="S00483.1.1.1.1.41">להם</w>
                         <w xml:id="S00483.1.1.1.1.42">אם</w>
                         <w xml:id="S00483.1.1.1.1.43">לא</w>
                         <lb n="7"/>
                         <w xml:id="S00483.1.1.1.1.44">עלה</w>
                         <w xml:id="S00483.1.1.1.1.45">עמוד</w>
                         <w xml:id="S00483.1.1.1.1.46">השחר</w>
                         <w xml:id="S00483.1.1.1.1.47">מותרין</w>
                         <w xml:id="S00483.1.1.1.1.48">אתם</w>
                         <w xml:id="S00483.1.1.1.1.49">לקרות</w>
                         <pc type="unitEnd" rend="null"/>
                         <milestone unit="MSMishnah" n="3"/>
                         <label>ג<am rend="null">׳</am>
                         </label>
                         <w xml:id="S00483.1.1.1.1.50">ולא</w>
                         <lb n="8"/>
                         <w xml:id="S00483.1.1.1.1.51">זו</w>
                         <w xml:id="S00483.1.1.1.1.52">בלבד</w>
                         <w xml:id="S00483.1.1.1.1.53">אלא</w>
                         <w xml:id="S00483.1.1.1.1.54">כל</w>
                         <w xml:id="S00483.1.1.1.1.55">שאמרו</w>
                         <w xml:id="S00483.1.1.1.1.56">חכמים</w>
                         <w xml:id="S00483.1.1.1.1.57">עד</w>
                         <w xml:id="S00483.1.1.1.1.58">חצות</w>
                         <surplus reason="fill">מצ<am rend="null">׳</am>
                         </surplus>
                         <lb n="9"/>
                         <w xml:id="S00483.1.1.1.1.59">מצותן</w>
                         <w xml:id="S00483.1.1.1.1.60">עד</w>
                         <w xml:id="S00483.1.1.1.1.61">שיעלה</w>
                         <w xml:id="S00483.1.1.1.1.62">עמוד</w>
                         <w xml:id="S00483.1.1.1.1.63">השחר</w>
                         <pc type="unitEnd" rend="null"/>
                         <milestone unit="MSMishnah" n="4"/>
                         <label>ד<am rend="null">׳</am>
                         </label>
                         <w xml:id="S00483.1.1.1.1.64">הקטר</w>
                         <lb n="10"/>
                         <w xml:id="S00483.1.1.1.1.65">חלבים</w>
                         <w xml:id="S00483.1.1.1.1.66">ואיברין</w>
                         <delSpan spanTo="#d1e217" hand="#h2" rend="deletion-mark"/>
                         <w xml:id="S00483.1.1.1.1.67">ואכילת</w>
                         <w xml:id="S00483.1.1.1.1.68">פסחים</w>
                         <anchor xml:id="d1e217" type="del"/>
                         <w xml:id="S00483.1.1.1.1.69">מצותן</w>
                         <w xml:id="S00483.1.1.1.1.70">עד</w>
                         <lb n="11"/>
                         <w xml:id="S00483.1.1.1.1.71">שיעלה</w>
                         <w xml:id="S00483.1.1.1.1.72">עמוד</w>
                         <w xml:id="S00483.1.1.1.1.73">השחר</w>
                         <pc type="unitEnd" rend="null"/>
                         <milestone unit="MSMishnah" n="5"/>
                         <label>ה<am rend="null">׳</am>
                         </label>
                         <w xml:id="S00483.1.1.1.1.74">וכל</w>
                         <w xml:id="S00483.1.1.1.1.75">הנאכלין</w>
                         <w xml:id="S00483.1.1.1.1.76">ליום</w>
                         <lb n="12"/>
                         <w xml:id="S00483.1.1.1.1.77">אחד</w>
                         <w xml:id="S00483.1.1.1.1.78">מצותן</w>
                         <w xml:id="S00483.1.1.1.1.79">עד</w>
                         <w xml:id="S00483.1.1.1.1.80">שיעלה</w>
                         <w xml:id="S00483.1.1.1.1.81">עמוד</w>
                         <w xml:id="S00483.1.1.1.1.82">השחר</w>
                         <w xml:id="S00483.1.1.1.1.83">אם</w>
                         <w xml:id="S00483.1.1.1.1.84">כן</w>
                         <lb n="13"/>
                         <w xml:id="S00483.1.1.1.1.85">למה</w>
                         <w xml:id="S00483.1.1.1.1.86">אמרו</w>
                         <w xml:id="S00483.1.1.1.1.87">חכמים</w>
                         <w xml:id="S00483.1.1.1.1.88">עד</w>
                         <w xml:id="S00483.1.1.1.1.89">חצות</w>
                         <w xml:id="S00483.1.1.1.1.90">אלא</w>
                         <w xml:id="S00483.1.1.1.1.91">להרחיק</w>
                         <w xml:id="S00483.1.1.1.1.92">את</w>
                         <lb n="14"/>
                         <w xml:id="S00483.1.1.1.1.93">האדם</w>
                         <w xml:id="S00483.1.1.1.1.94">מן</w>
                         <w xml:id="S00483.1.1.1.1.95">העבירה</w>
                         <pc type="unitEnd" rend="null"/>
                      </ab>"""
    
    soup = BeautifulSoup(xml_text, "html.parser")
    for ab in soup.select("ab"):
        text = " ".join(w.text for w in ab.select("w"))
        print(ab["xml:id"], end=" ")
        print(text)
    

    Prints:

    S00483.1.1.1.1 מאמתי קורין את שמע בערבים משעה שהכהנים נכנסין לאכל בתרומתן עד סוף האשמורת הראשנה דברי רבי אליעזר וחכמין אומרין עד חצות רבן גמליאל אומר עד שיעלה עמוד השחר מעשה שבאו בניו מבית המשתה אמרו לו לא קרינו את שמע אמר להם אם לא עלה עמוד השחר מותרין אתם לקרות ולא זו בלבד אלא כל שאמרו חכמים עד חצות מצותן עד שיעלה עמוד השחר הקטר חלבים ואיברין ואכילת פסחים מצותן עד שיעלה עמוד השחר וכל הנאכלין ליום אחד מצותן עד שיעלה עמוד השחר אם כן למה אמרו חכמים עד חצות אלא להרחיק את האדם מן העבירה