[英]Using xslt append new element in xml data
I am trying to add a new element to my XML file data as below:我正在尝试向我的 XML 文件数据添加一个新元素,如下所示:
Orignal :原件:
<storage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.0" ssd-storage="hybrid">
<server port="6890" />
<data-store name="mystore1" limit="700">
<data-dir>${SSD_STORE_BASE}/myFolder1</data-dir>
</data-store>
<data-store name="mystore2" limit="700">
<data-dir>${HDD_STORE_BASE}/myFolder2</data-dir>
</data-store>
<data-store name="mystore3" limit="700">
<data-dir>${SSD_STORE_BASE}/myFolder3</data-dir>
</data-store>
.... many such data-stores for both HDD and SSD
</storage>
Expected预期的
<storage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.0" ssd-storage="hybrid">
<server port="6890" />
<data-store name="mystore1" limit="700">
<data-dir>${SSD_STORE_BASE1}/myFolder1</data-dir>
<data-dir>${SSD_STORE_BASE2}/myFolder1</data-dir>
</data-store>
<data-store name="mystore2" limit="700">
<data-dir>${HDD_STORE_BASE1}/myFolder2</data-dir>
<data-dir>${HDD_STORE_BASE2}/myFolder2</data-dir>
</data-store>
<data-store name="mystore3" limit="700">
<data-dir>${SSD_STORE_BASE1}/myFolder3</data-dir>
<data-dir>${SSD_STORE_BASE2}/myFolder3</data-dir>
</data-store>
.... many such data-stores for both HDD and SSD
</storage>
I want to pass the replacement parameters for SSD_STORE_BASE and HDD_STORE_BASE, and the XSLT will need to append a copy of "data-dir" element with a replaced value of the text in the element.我想传递 SSD_STORE_BASE 和 HDD_STORE_BASE 的替换参数,而 XSLT 将需要 append 的“data-dir”元素的副本,其中包含元素中文本的替换值。 How do I do this?我该怎么做呢? If I can use xsltproc to do this, that would be perfect.如果我可以使用 xsltproc 来做到这一点,那将是完美的。
You can achieve that with the following XSLT-1.0 stylesheet which can be processed by xsltproc
with parameters.您可以使用以下 XSLT-1.0 样式表来实现这一点,该样式表可由xsltproc
使用参数进行处理。 Set the parameters with设置参数
xsltproc --stringparam replacementSSD "newSSDValue" --stringparam replacementHDD "newHDDValue" transform.xslt input.xml
This can be transform.xslt
:这可以是transform.xslt
:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="replacementSSD" select="'SSD_STORE_BASE'" />
<xsl:param name="replacementHDD" select="'HDD_STORE_BASE'" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="data-dir[contains(.,'SSD_STORE_BASE')]">
<xsl:copy>
<xsl:value-of select="concat(substring-before(.,'SSD_STORE_BASE'),$replacementSSD,'1',substring-after(.,'SSD_STORE_BASE'))" />
</xsl:copy>
<xsl:text>
</xsl:text>
<xsl:copy>
<xsl:value-of select="concat(substring-before(.,'SSD_STORE_BASE'),$replacementSSD,'2',substring-after(.,'SSD_STORE_BASE'))" />
</xsl:copy>
</xsl:template>
<xsl:template match="data-dir[contains(.,'HDD_STORE_BASE')]">
<xsl:copy>
<xsl:value-of select="concat(substring-before(.,'HDD_STORE_BASE'),$replacementHDD,'1',substring-after(.,'HDD_STORE_BASE'))" />
</xsl:copy>
<xsl:copy>
<xsl:value-of select="concat(substring-before(.,'SSD_STORE_BASE'),$replacementHDD,'2',substring-after(.,'HDD_STORE_BASE'))" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This stylesheet could be optimized by merging the two templates, but I left them separately, because they may contain different functionality.这个样式表可以通过合并两个模板来优化,但是我把它们分开了,因为它们可能包含不同的功能。
An updated answer reflecting the new requirements:反映新要求的更新答案:
Counting is a bit complicated in XSLT-1.0, so I created a data-island that takes care of that - named cnt:counter
.在 XSLT-1.0 中计数有点复杂,所以我创建了一个数据岛来处理这个问题 - 命名为cnt:counter
。 In this example it counts up to three.在此示例中,它最多计数为 3。 Then, in the code, it iterates over this element to count up to three - the main string is preserved in a variable.然后,在代码中,它迭代这个元素以计数到三个 - 主字符串保存在一个变量中。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cache="geode.apache.org/schema/cache" xmlns:cnt="http://count.com">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="replacementSSD" select="'SSD_STORE_BASE'" />
<xsl:param name="replacementHDD" select="'HDD_STORE_BASE'" />
<cnt:counter>
<cnt:cnt>1</cnt:cnt>
<cnt:cnt>2</cnt:cnt>
<cnt:cnt>3</cnt:cnt>
</cnt:counter>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="cache:data-dir[contains(.,'SSD_STORE_BASE')]">
<xsl:variable name="curStr" select="." />
<xsl:for-each select="document('')/xsl:stylesheet/cnt:counter/cnt:cnt">
<xsl:element name="data-dir" namespace="geode.apache.org/schema/cache">
<xsl:value-of select="concat(substring-before($curStr,'SSD_STORE_BASE'),$replacementSSD,.,substring-after($curStr,'SSD_STORE_BASE'))" />
</xsl:element>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:template match="cache:data-dir[contains(.,'HDD_STORE_BASE')]">
<xsl:variable name="curStr" select="." />
<xsl:for-each select="document('')/xsl:stylesheet/cnt:counter/cnt:cnt">
<xsl:element name="data-dir" namespace="geode.apache.org/schema/cache">
<xsl:value-of select="concat(substring-before($curStr,'HDD_STORE_BASE'),$replacementHDD,.,substring-after($curStr,'HDD_STORE_BASE'))" />
</xsl:element>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Its output is:其 output 为:
<storage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="geode.apache.org/schema/cache" version="1.0" ssd-storage="hybrid">
<server port="6890"/>
<data-store name="mystore1" limit="700">
<data-dir>${SSD_STORE_BASE1}/myFolder1</data-dir>
<data-dir>${SSD_STORE_BASE2}/myFolder1</data-dir>
<data-dir>${SSD_STORE_BASE3}/myFolder1</data-dir>
</data-store>
<data-store name="mystore2" limit="700">
<data-dir>${HDD_STORE_BASE1}/myFolder2</data-dir>
<data-dir>${HDD_STORE_BASE2}/myFolder2</data-dir>
<data-dir>${HDD_STORE_BASE3}/myFolder2</data-dir>
</data-store>
<data-store name="mystore3" limit="700">
<data-dir>${SSD_STORE_BASE1}/myFolder3</data-dir>
<data-dir>${SSD_STORE_BASE2}/myFolder3</data-dir>
<data-dir>${SSD_STORE_BASE3}/myFolder3</data-dir>
</data-store>
.... many such data-stores for both HDD and SSD
</storage>
This solution does handle the newly introduced namespace and the counting in XSLT-1.0.这个解决方案确实处理了新引入的命名空间和 XSLT-1.0 中的计数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.