There are two stages of "working" with DOM.
The first stage is the server render. When PHP engine receives template (mix of HTML, PHP) plus data and outputs valid HTML to a browser. In this stage, you can build HTML that will be parsed by a browser to DOM tree. You don't work with DOM, but rather with a plain text of your template.
The second stage is the Javascript evaluation. A browser parses and runs JS, and this JS has access to DOM tree.
The first stage can be done in any language that runs on a server. You can use c# templates, python templates, go templates, even javascript. All template engines just proceed template (text) and data and give text output which can be valid HTML.
The second stage works only with JS because browsers work with JS only. There were some attempts to bring other languages to a frontend (like Dart), and all failed. But you have some options. There are many compilers for existing languages that can target JS. For example, clojruescript for clojure, bucklescript for ocaml, gopherjs for go and others. Also, there are bunch of languages which created for this purpose (compile to JS): purescript, elm, typescript, etc.
Modern browsers can use webassembly binary packages. It differs from JS, but also don't have access to DOM.