Это интересная проблема. Я предполагаю, что $/some/path/$
всегда будет заменен значением элементов, возвращаемых запросом XPath? Я думаю, что «Файл» должен быть обработан как строка. Да, это XML, но если этот шаблон верен, то все намного проще. Тогда это просто макрозамена.
В этом случае одним из решений будет (скрипт Scala):
import scala.xml.{Node, NodeSeq}
val pattern = """\$([\w/]*)\$""".r
def patterns(s: String) = (pattern findAllIn s matchData) map (_ group 1) toList
def pathComponents(path: String) = (path split """\b(?!\w)""" toList) map (_ split "\\b" toList)
def lookUp(xml: Node, path: List[List[String]]) = {
path.foldLeft(xml : NodeSeq) { (nodes, pathComponent) =>
pathComponent match {
case List("/", component) => nodes \ component
case List("//", component) => nodes \\ component
case _ => throw new IllegalArgumentException
}
} map (_ text)
}
def pathAndValues(s: String, xml: Node) = {
patterns(s) map (path => (path -> lookUp(xml, pathComponents(path))))
}
def merge(s: String, xml: Node) = {
pathAndValues(s, xml).foldLeft(List(s)) { (files, tuple) =>
val (path, values) = tuple
for (file <- files;
value <- values)
yield file replace ("$"+path+"$", value)
}
}
Затем вы читаете XmlDocument в xml и файл, который нужно объединить в String. Это, конечно, предполагает, что файл не слишком большой для такой обработки. В Scala это можно сделать так:
merge(scala.io.Source.fromFile(filename).getLines.mkString,
scala.xml.XML.loadFile(XmlDocumentFilename))
Это вернет список с каждой возможной перестановкой для каждой замены.
Если эти файлы слишком велики для хранения в памяти, потребуется сгенерировать каждую возможную перестановку для заменяемых значений, так что вам потребуется только один проход для замены всех путей для каждой перестановки.
Если XPath являются истинными XPath, а не ограничиваются только "/" и "//", это решение не будет работать как есть. Он должен быть преобразован, чтобы использовать настоящую библиотеку XPath. Также обратите внимание, что «/» ищет дочернего элемента, поэтому, если <data>
является корнем, /data
не будет работать.