Powered by AppSignal & Oban Pro

XML extractor App

livebooks/myapp.livemd

XML extractor App

Mix.install([
  {:kino, "~> 0.17.0"},
  {:sweet_xml, "~> 0.7.5"}
])

Section

IDEx XML Extractor

This app extracts the important information retreived from Diagnostics output from IDEx tool

defmodule FileHandler do

  def get() do
    Kino.Input.file("Upload your file", accept: ~w(.xml))
  end

  def read(file_ref) do
    path = Kino.Input.file_path(file_ref)
    %{path: path, content: File.read!(path)}
  end
end
defmodule Ecu do
  @enforce_keys [:id]
  defstruct id: "",
            swv: ""
end

defmodule User do
  defstruct name: "",
            client: "",
            file: "",
            time: "",
            date: ""

  def to_string(user) do
    """
    ### File:
     #{user.file}
    | User | PC Name| date| time|
    | :---: | :---:| :---:| :---: |
    | #{user.name}  | #{user.client}| #{user.date} | #{user.time}|
    """
  end
end

defmodule VehicleData do
  defstruct km: 0,
            vin: "",
            name: ""

  def to_string(vehicle) do
    """
    | Name | VIN| Km| 
    | :---: | :---:| :---:| 
    | #{vehicle.name}  | #{vehicle.vin}| #{vehicle.km} |
    """
  end
end
defmodule XmlHandler do
  import SweetXml

  def getUser(content) do
    %User{
      name: content |> xpath(~x"//User/text()"S),
      client: content |> xpath(~x"//ClientName/text()"S),
      file: content |> xpath(~x"//Dateiname/text()"S),
      time: content |> xpath(~x"//Zeit/text()"),
      date: content |> xpath(~x"//Datum/text()")
    }
  end

  def getVehicleData(content) do
    %VehicleData{
      vin: content |> xpath(~x"//Fahrgestellnummer/text()"S),
      km: content |> xpath(~x"//WegStrecke/text()"i),
      name: content |> xpath(~x"//UserProjekt/text()"S)
    }
  end

  def getEcus(content) do
    diagnostics =
      content
      |> xmap(
        Diagnosebloecke: [
          ~x"//Diagnosebloecke/Diagnoseblock"l,
          id: ~x"./Adresse/text()"S,
          sw: ~x"./SWVersion/text()"S,
          description: ~x"./Systembezeichnung/text()"S
        ]
      )

    Map.get(diagnostics, :Diagnosebloecke)
  end

  def getEcus(content, ids) do
    diagList = getEcus(content)
    a = Enum.map(ids, fn id -> Enum.filter(diagList, fn map -> map.id == id end) end)
    List.flatten(a)
  end
end
form =
  Kino.Control.form(
    [
      file: FileHandler.get()
    ],
    submit: "Parse"
  )

outputFrame = Kino.Frame.new()

h1 =
  Kino.HTML.new("""
  <h1>IDEx XML Parser</h1>

  <p>This app helps you decode and extract the specific fields of the IDEx XML file.</p>
  """)

Kino.listen(form, fn event ->
  %{data: %{file: %{file_ref: file_ref}}} = event
  Kino.Frame.render(outputFrame, "Parsing XML...")

  # {:file, validator} = file_ref
  # if validator == "" do
  #   Kino.interrupt!(:error, "Please provide the XML file..")
  # end

  v = FileHandler.read(file_ref)

  userDetails =
    v.content
    |> XmlHandler.getUser()
    |> User.to_string()
    |> Kino.Markdown.new()

  vehicleDetails =
    v.content
    |> XmlHandler.getVehicleData()
    |> VehicleData.to_string()
    |> Kino.Markdown.new()

  tabs =
    Kino.Layout.tabs(
      User: userDetails,
      Vehicle: vehicleDetails,
      Important_IDs:
        Kino.DataTable.new(
          XmlHandler.getEcus(v.content, ["0009", "0019", "8103", "8124", "812C"])
        ),
      All_IDs: Kino.DataTable.new(XmlHandler.getEcus(v.content))
    )

  Kino.Frame.render(outputFrame, tabs)
end)

Kino.Layout.grid([h1, form, outputFrame])