XSLT-“应用”更新到另一个文件

时间:2018-10-02 17:59:07

标签: xslt

我有一些Tomcat配置,我正在尝试自动进行更改。可能看起来像这样:

<web-app>
  <!-- many other configuration options here... -->
  <session-config>
    <session-timeout>30</session-timeout>
  </session-config>
  <!-- many other configuration options here... -->
<web-app>

我只想更新一个值,而其他内容保持不变。因此,我定义了一个具有相同结构的文件,只是我要在其中更改的值:

<web-app>
  <session-config>
    <session-timeout>15</session-timeout>
  </session-config>
<web-app>

这是我的XSLT,将更新文件作为输入,并将“默认” TC配置文件路径作为参数:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" version="1.0" encoding="UTF-8" />
  <xsl:param name="tcInputFilePath" />
  <xsl:param name="tcInputFile" select="document($tcInputFilePath)" />

  <xsl:template match="/">
    <xsl:apply-templates select="$tcInputFile/*" />
  </xsl:template>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates="@*|node()" />
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

基本上,我想要一份$tcInputFile的副本,并从更新文件中应用更改。我的猜测是,我需要某种方式在遍历TC文件时在更新文件中查找相同的路径,然后进行测试以查看该路径是否没有子节点,并应用value-of而不是copy(如果是)。我只是不知道在遍历时如何在另一个文档中选择“相同节点”。帮助吗?

1 个答案:

答案 0 :(得分:1)

有关类似问题的通用XSLT 3解决方案,请参见http://xslt-3-by-example.blogspot.com/2017/06/using-xslevaluate-and-path-function-to.html,尽管输入中有要更新的空元素,对于您的情况,您需要解释并实现一种检查相关元素的方法。而且该解决方案需要xsl:evaluate,只有在Saxon 9.8和9.9的商业版本中可用。

由于Saxon 9.8和9.9所有版本都支持transform函数https://www.w3.org/TR/xpath-functions/#func-transform,因此这些XSLT 3处理器中的问题也可以通过动态生成样式表并运行来解决:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:axsl="http://www.w3.org/1999/XSL/Transform-alias"
    exclude-result-prefixes="#all"
    expand-text="yes"
    version="3.0">

  <xsl:param name="config-doc">
    <web-app>
      <foo-config>
          <foo-value>foo</foo-value>
      </foo-config>
      <!-- many other configuration options here... -->
      <session-config>
        <session-timeout>30</session-timeout>
      </session-config>
      <!-- many other configuration options here... -->
      <bar-config>
          <bar-value>bar</bar-value>
      </bar-config>
    </web-app>      
  </xsl:param>

  <xsl:output indent="yes"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>

  <xsl:variable name="stylesheet">
      <axsl:stylesheet version="3.0" exclude-result-prefixes="#all">
          <axsl:mode on-no-match="shallow-copy"/>
          <xsl:for-each select="//text()[normalize-space()]">
              <axsl:template match="{path()}">{.}</axsl:template>
          </xsl:for-each>
      </axsl:stylesheet>
  </xsl:variable>

  <xsl:template match="/">
     <xsl:sequence select="transform(map { 'source-node' : $config-doc, 'stylesheet-node' : $stylesheet })?output"/>
  </xsl:template>

</xsl:stylesheet>

主配置文件已内联,但是您当然可以使用documentdoc来加载它。

https://xsltfiddle.liberty-development.net/3NzcBtM上的在线示例。