我需要使用简单的配置更新许多xml文件。我遇到的问题 - config
元素在我的xml文件中是可选的,它们已经有了一些配置。
所以我想做的事情:
<config/>
,请插入element
element
插入config
标记。如果他们已经在那里 - 原样离开。之前的 :
<root>
<config> <!-- this is optional. can be not defined at all -->
<element2 attr="c"/>
</config>
</root>
我想要的是什么:
<root>
<config>
<element1 attr="a"/>
<element2 attr="b"/> <!-- not override this one, but insert if missing -->
<element3 attr="c"/>
</config>
</root>
所以我的想法是有几个模板,如果它不存在则应用第一步,并在单独的mode
内进行第二步。但它没有成功。
UPD。 我使用xslt 1.0,但我猜测切换到2.0将不是问题。
预定义的元素是:
<element1 attr="a"/>
<element2 attr="b"/>
<element3 attr="c"/>
答案 0 :(得分:3)
这是一个XSLT样式表:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output indent="yes"/>
<xsl:key name="cfg-els-by-name" match="config/*" use="node-name(.)"/>
<xsl:param name="default">
<config>
<element1 attr="a"/>
<element2 attr="b"/>
<element3 attr="c"/>
</config>
</xsl:param>
<xsl:variable name="main-doc" select="/"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root[not(config)]">
<xsl:copy>
<xsl:copy-of select="$default/config"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root/config">
<xsl:copy>
<xsl:apply-templates select="* , $default/config/*[not(key('cfg-els-by-name', node-name(.), $main-doc))]">
<xsl:sort select="local-name(.)"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我不确定config
子元素的顺序是否通过local-name()
上的排序来确定。
答案 1 :(得分:2)
您需要进行近似身份转换,并进行一些修改。
首先是类似英语的伪代码:
root
的模板中,分别处理这两种情况:如果你有一个config
元素,则处理它;否则,供应一个。现在,在类似XSLT的伪代码中:
在root
的模板中,分别处理这两种情况:
<xsl:template match='root'>
<xsl:copy>
<xsl:choose>
<xsl:when test="config">
<xsl:apply-templates/>
</
<xsl:otherwise>
<config>
<element1 attr="a"/>
<element2 attr="b"/>
<element3 attr="c"/>
</config>
</
</
</
</
在config
的模板中,根据需要提供缺少的元素。如果您有固定的订单,代码可以按顺序遍历它们:
<xsl:template match='config'>
<xsl:copy>
<xsl:choose>
<xsl:when test="element1">
<xsl:apply-templates select="element1"/>
</
<xsl:otherwise>
<element1 attr="a"/>
</
</
<xsl:choose>
<xsl:when test="element2">
<xsl:apply-templates select="element2"/>
</
<xsl:otherwise>
<elementb attr="b"/>
</
</
<!--* more chooses, as needed ... *-->
<xsl:choose>
<xsl:when test="elementN">
<xsl:apply-templates select="elementN"/>
</
<xsl:otherwise>
<elementN attr="N"/>
</
</
</
</
如果订单不受约束,这可能会更简单一些:
<xsl:template match="config">
<xsl:copy>
<xsl:apply-templates/>
<xsl:if test="not(element1)">
<element1 attr="a"/>
</
<xsl:if test="not(element2)">
<element2 attr="b"/>
</
<!--* etc ... *-->
</
</
除非你做的事情比你表现得更复杂,否则我认为不需要额外的模式。
答案 2 :(得分:2)
config
,并使用原始config
中的现有值或 - 如果找不到任何值 - 来安装您自己的默认值。
这是 XSLT 1.0 实施:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="cfg" match="config/*" use="local-name()" />
<xsl:variable name="default-cfg">
<element1 attr="a"/>
<element2 attr="b"/>
<element3 attr="c"/>
</xsl:variable>
<xsl:variable name="root" select="/"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root">
<xsl:copy>
<config>
<xsl:for-each select="exsl:node-set($default-cfg)/*">
<xsl:call-template name="cfg-element"/>
</xsl:for-each>
</config>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="config"/>
<xsl:template name="cfg-element">
<xsl:variable name="name" select="name()"/>
<xsl:variable name="default-value" select="@attr"/>
<xsl:for-each select="$root">
<xsl:variable name="existing-element" select="key('cfg', $name)"/>
<xsl:element name="{$name}">
<xsl:attribute name="attr">
<xsl:choose>
<xsl:when test="$existing-element">
<xsl:value-of select="$existing-element/@attr"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$default-value"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>