Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I am having a lot of data in .xml files which look like this:

<DATA>
  <NAME="name" />
  <VERSION="1" />
  <VARIABLES>
    <TEST>
      <ELEMENT atr="0" atr2="1">123456.000000001</ELEMENT>
    </TEST>
  </VARIABLES>
</DATA>

I have to write a lot of templates reading this data for documentation and I would like to do this with LaTeX. Does any approach exist, to write this data into a .tex file? I want to write a file, where each {SOMETHING/SOMETHINGELSE} gets replaced by the XML value. A bonus would be, to get it rounded. As I am using LuaLaTeX, I guess there could be an approach in this language. But any other possibility would be interesting for me, too. Unluckily, I am not the scripting guy, but if you say, I should do this in python (which I would be willing to learn...), I will move this to an other SX-page.

The file would look something like this:

% arara: lualatex

\documentclass{article}
\usepackage{booktabs}
\usepackage{siunitx}

\begin{document}
\section{VolumeFlows}
A variable: $x=\SI{{VARIABLES/TEST/ELEMENT}}{\metre}$

\begin{table}%
\centering
\begin{tabular}{l S}
\toprule
Name & {Value}\\
\midrule
A variable & {VARIABLES/TEST/ELEMENT}\\
\bottomrule
\end{tabular}
\end{table}
\end{document}
share|improve this question
2  
Have you tried searching for xml parser lua on Google? –  Jubobs May 13 at 12:35
    
@Jubobs, yes, that's how I got the idea, but I have no skills in this and would not know, how to include it and less, how to replace existing strings by the parsed data. Sorry, I know that I want to do things here, which are way above my knowledge. But maybe some trick already exists. –  LaRiFaRi May 13 at 12:44
2  
you could use an xml parser from lua or an xml parser written in tex (xmltex) or (what I would do) just use xslt or any other xml tool of choice and write out the data in tex syntax to input into tex, there isn't any particular advantage in calling the xml parser from lua as opposed to simply calling it first –  David Carlisle May 13 at 12:50
    
@DavidCarlisle XSLT would be new to me, too. I'll have a look. But you are right, it would be ok to write my file first and to compile the .tex afterwards. But if I want to distribute the template, a version like cjorssens would be really handy, as I just need to run LuaLaTeX ones. –  LaRiFaRi May 13 at 13:11
add comment

1 Answer 1

up vote 7 down vote accepted

Here is the general idea with the luaxml "package".

\documentclass{article}
\usepackage{luacode}
\begin{luacode*}
xml = require('luaxml-mod-xml')
handler = require('luaxml-mod-handler')
\end{luacode*}
\begin{document}
\begin{luacode*}
sample = [[
<DATA>
  <NAME="name" />
  <VERSION="1" />
  <VARIABLES>
    <TEST>
      <ELEMENT atr="0" atr2="1">123456.000000001</ELEMENT>
    </TEST>
  </VARIABLES>
</DATA>]]
treehandler = handler.simpleTreeHandler()
x = xml.xmlParser(treehandler)
x:parse(sample)
tex.sprint(treehandler.root["DATA"]["VARIABLES"]["TEST"]["ELEMENT"])
\end{luacode*}
\end{document}

EDIT

Probably a bit better but it's been a long time since I wrote some lua code...

% arara: lualatex

\documentclass{article}
\usepackage{siunitx}
\usepackage{booktabs}
\usepackage{luacode}
\begin{luacode*}
xml = require('luaxml-mod-xml')
handler = require('luaxml-mod-handler')
treehandler = handler.simpleTreeHandler()
xmlparser = xml.xmlParser(treehandler)

function readxmlfile(filename)
  local f = assert(io.open(filename, 'r'))
  local t = f:read('*all')
  f:close()
  return t
end

function parsexmlstring(string)
  xmlparser:parse(string)  
end
\end{luacode*}

\def\parsexmlfile#1{%
  \directlua{%
    parsexmlstring(readxmlfile('#1'))}}
\def\getxmlvalue#1#2#3#4{%
  \directlua{%
    tex.sprint(treehandler.root['#1']['#2']['#3']['#4'])}}    

\parsexmlfile{sample.xml}

\begin{document}
Variable: $x=\SI[round-mode=places,round-precision=1]{\getxmlvalue{DATA}{VARIABLES}{TEST}{ELEMENT}}{\metre}$

\begin{table}%
\centering
\begin{tabular}{l S[round-mode=places,round-precision=4]}
\toprule
Name & {Value}\\
\midrule
A variable & \getxmlvalue{DATA}{VARIABLES}{TEST}{ELEMENT}\\
\bottomrule
\end{tabular}
\end{table}
\end{document}

with sample.xml

<DATA>
  <NAME="name" />
  <VERSION="1" />
  <VARIABLES>
    <TEST>
      <ELEMENT atr="0" atr2="1">123456.000000001</ELEMENT>
    </TEST>
  </VARIABLES>
</DATA>
share|improve this answer
    
Thank you! That was quick and looks really promising. But do I need such a block for every variable? Could you show me how to insert a myData.xml and write the line A variable: $x=\SI{{VARIABLES/TEST/ELEMENT}}{\metre}$? –  LaRiFaRi May 13 at 13:08
1  
Sorry, I don't have time to address the requirement with VARIABLES/TEST/ELEMENT). Maybe later. Probably some lpeg magic. –  cjorssen May 13 at 13:34
    
Thank you very very much. This works just great. I just edited to insert my requirements of rounded values and the use of your macro inside of other stuff like tables. The slash-notation without the need of calling the root each time would still be nice, but I can work with this for now. Great. I guess, I can just read values from fourth level like this? I will give it a try or define other macros for bigger levels. –  LaRiFaRi May 13 at 13:51
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.