我正在尝试使用XSLT重新格式化一些XML。我输入的片段如下所示:
<toggles>
<toggle toggleDisplayName="Charges">
<anotherElement attribute="value" />
<gridColumn sourceField.name="FIELD1" />
<gridColumn sourceField.name="FIELD2" />
<gridColumn sourceField.name="FIELD3" />
</toggle>
</toggles>
我想将所有'gridColumn'元素包装成一个'grid'元素,如下所示:
<toggles>
<toggle toggleDisplayName="Charges">
<anotherElement attribute="value" />
<grid>
<gridColumn sourceField.name="FIELD1" />
<gridColumn sourceField.name="FIELD2" />
<gridColumn sourceField.name="FIELD3" />
</grid>
</toggle>
</toggles>
我目前的XSLT是:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="toggle/gridColumn">
<grid>
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</grid>
</xsl:template>
<!--Identity transform for remaining-->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
现在这种工作,但我在每个'grid'元素中都有'gridColumn'元素。有没有简单的方法来修改它,以便我可以获得上述结果?
注意:编辑以澄清输入XML。
提前感谢您的帮助!
答案 0 :(得分:1)
我能想到的最简单的变体,如果所有gridColumn
元素在原始输入XML中相邻(形成一个没有其他插入元素的连续块),则该变量有效:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*" />
<xsl:output method="xml" indent="yes"/>
<xsl:template match="toggle">
<xsl:copy>
<!-- apply templates to everything except the second and subsequent
gridColumn child elements -->
<xsl:apply-templates select="@* | node()[not(self::gridColumn)]
| gridColumn[1]" />
</xsl:copy>
</xsl:template>
<!-- this template will be called for just the first gridColumn within
a toggle... -->
<xsl:template match="gridColumn">
<grid>
<!-- ... and will gather all its sibling gridColumn elements under the
new grid element -->
<xsl:copy-of select="../gridColumn" />
</grid>
</xsl:template>
<!--Identity transform for remaining-->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
如果gridColumn
元素并非全部相邻,我们会发现他们已经在第一个的地方聚集到一个<grid>
中em> gridColumn
出现在输入XML中。
答案 1 :(得分:0)
我提出了这个解决方案。请检查它是否符合您的所有要求。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes" />
<!-- Process toggle separately, because its childredn cannot simply be copied -->
<xsl:template match="toggle">
<xsl:copy>
<xsl:apply-templates select="./@*" /> <!-- For some unknown reason I needed this -->
<xsl:apply-templates />
<grid>
<xsl:for-each select="gridColumn">
<xsl:copy-of select="." />
</xsl:for-each>
</grid>
</xsl:copy>
</xsl:template>
<xsl:template match="gridColumn">
<!-- Do nothing, because it is processed by for-each -->
</xsl:template>
<!--Identity transform for remaining-->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>