
這段程式碼幾乎不會解析 XML 並將其列印為 SXML(s-exp XML,又稱 lisp 風格的 XML,又稱為 XML-with-parenthesis):
\catcode`@=11
\let\@xp\expandafter
\def\@makeletter#1#2\@nil{\catcode`#1 \ifx\relax#2\relax\else\@makeletter#2\@nil\fi}
\def\@gobble#1 {}
\def\@nil{}
\catcode`<13
\catcode`>12
\def\@split #1#2 #3\@nil{#1{#2} \ifx\relax#3\relax\else\@split#1#3\@nil\fi}
\def\defelt#1{\def<#1##1>##2</#1>{ (#1 {\ifx\relax##1\relax\else \@xp\@split\@xp\@key\@gobble ##1 \@nil\fi} ##2) }}
\defelt{div}
\defelt{span}
\catcode`?6
\catcode`#11
\def\@key?1=?2{ {\tt #:?1} ?2}
\def\@key?1{ {\tt #:?1}}
\catcode`^^J=10 \catcode`?=11 \catcode`^=11 \catcode`_=11 \catcode`~=11 \catcode`{=11 \catcode`}=11 %\catcode`\=11
%\@makeletter?^_~{}%\@nil
<span>first<span foo bar=yes>second</span>three</span>
\eject
\end
第一個問題是重新定義\
catcode不起作用,因為之後\<string>
仍然給出「未定義的控制序列」錯誤,第二個問題(不太重要)是我無法編寫循環來重複重新定義catcode,第三個問題也是最重要的:
為什麼 TeX 不支援巨集重載?我的意思是,就像你可以看到我對 所做的那樣\xattr
,但是,最糟糕的是,它\defelt
重新定義了“<”,並在其參數之間添加了一些內容。問題是要么我找到一種方法使“<”控制序列模擬所有xml 標籤,要么我將“<”catcode 0 設為0,然後這意味著我必須從我想要的XML 中授予對aaaall TeX 控制序列的存取權限parse(這很難看):那我該怎麼做呢?
除了單獨定義 < 命令然後遞歸讀取後面的文字而不受益於 TeX 解析功能之外,還有其他解決方案嗎?
答案1
假設以下輸入範例:
<?xml version="1.0" encoding="utf8"?>
<cenik>
<nazev>Počítačové komponenty</nazev>
<platnost od="1.1.2000" do="31.3.2000"/>
<dodavatel>
<nazev>První hardwarová, s.r.o.</nazev>
<adresa>
<ulice>Průmyslová 12</ulice>
<mesto>Praha 10</mesto>
<psc>100 000</psc>
<email>[email protected]</email>
</adresa>
</dodavatel>
<nabidka>
<produkt kategorie="polohovací zařízení" kod="pxbd-21">
<nazev>Hyperoptická <em>digitální</em> myš</nazev>
<cena mena="CZK">368.30</cena>
</produkt>
<produkt kategorie="pevné disky" kod="sbhd-99">
<nazev>Soft-slow disc < 19,3 GB</nazev>
<cena mena="CZK">8500</cena>
</produkt>
<produkt kategorie="polohovací zařízení" kod="pxbd-13">
<nazev>Tlakový tablet</nazev>
<cena mena="CZK">5635.20</cena>
</produkt>
</nabidka>
</cenik>
然後嘗試透過我的巨集\xmlprep {input} {output}
使用pdftex thisfile
命令來處理它。
\newwrite\xmloutfile
\def\xmlprep#1#2{% #1=input file, #2=output file
\ifx\relax#2\relax \chardef\xmloutfile=16 \else
\immediate\openout\xmloutfile=#2 \fi
\begingroup \everypar={\setbox0=\lastbox\par \xscan}\input#1 \endgroup
\immediate\closeout\xmloutfile
}
\long\def\xscan#1<{\ifx\xscan#1\xscan \else
\toks0={#1}\xprint{\the\toks0\npercent}\fi\xtag}
\def\nob#1{}\edef\nob{\expandafter\nob\string\{}
\def\ncb#1{}\edef\ncb{\expandafter\ncb\string\}}
\def\npercent#1{}\edef\npercent{\expandafter\npercent\string\%}
\def\xprint#1{\immediate\write\xmloutfile{\xindent#1}}
\def\xindent{}
\def\xtag#1#2>{\ifx#1?\xtagD#2>\else\ifx#1/\xtagC#2>\else\xtagE#1#2>/>\end\fi\fi}
\def\xtagE#1/>#2\end{\ifx>#2>\let\tmp=n\xtagA#1 \end\else \let\tmp=/\xtagA#1> \end\fi}
\def\xtagA#1 #2\end{\def\currargs{}\ifx>#2>\xtagB#1\else \xargsB#2\xtagB#1>\fi}
\def\xtagB#1>{\bgroup\def\currtag{#1}%
\ifx\tmp/\xprint{\string\XML#1{\currargs}{}}\egroup\else
\xprint{\string\XML#1{\currargs}\nob\npercent}%
\edef\xindent{\xindent\space\space}\fi}
\def\xtagD#1?>{\xprint{\string\META{#1}}}
\def\xargsB#1>{\def\currargs{#1}}
\def\xtagC#1>{\def\tmp{#1}\ifx\tmp\currtag\else
\message{WARNING: <\currtag>...</#1> doesn't match}\fi
\egroup\xprint{\ncb}%
}
\xmlprep {test.xml} {test.out}
\end
您將得到以下輸出test.out
\META{xml version="1.0" encoding="utf8"}
\XMLcenik{}{%
\XMLnazev{}{%
Počítačové komponenty%
}
\XMLplatnost{od="1.1.2000" do="31.3.2000"}{}
\XMLdodavatel{}{%
\XMLnazev{}{%
První hardwarová, s.r.o.%
}
\XMLadresa{}{%
\XMLulice{}{%
Průmyslová 12%
}
\XMLmesto{}{%
Praha 10%
}
\XMLpsc{}{%
100 000%
}
\XMLemail{}{%
[email protected]%
}
}
}
\XMLnabidka{}{%
\XMLprodukt{kategorie="polohovací zařízení" kod="pxbd-21"}{%
\XMLnazev{}{%
Hyperoptická %
\XMLem{}{%
digitální%
}
myš%
}
\XMLcena{mena="CZK"}{%
368.30%
}
}
\XMLprodukt{kategorie="pevné disky" kod="sbhd-99"}{%
\XMLnazev{}{%
Soft-slow disc < 19,3 GB%
}
\XMLcena{mena="CZK"}{%
8500%
}
}
\XMLprodukt{kategorie="polohovací zařízení" kod="pxbd-13"}{%
\XMLnazev{}{%
Tlakový tablet%
}
\XMLcena{mena="CZK"}{%
5635.20%
}
}
}
}
這是 TeX 友好的格式。您可以簡單地定義使用的標籤\XMLcenik
等\XMLnazev
具有兩個參數(參數和正文文字)的巨集。然後你就可以用TeX來處理它了。如果準備好這些宏,那麼您可以在一次 TeX 運行中處理 XML 檔案:
\xmlprep {test.xml} {text.out}
\input test.out