拆分 XSLT 中的合并单元格
Demerge the merged cell in XSLT
谁能帮我解决下面的 xslt 问题。
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<cd>
<title rowmerge="f">Title 1</title>
<artist rowmerge="f">sample 1</artist>
<price rowmerge="T">1</price>
<year >1985</year>
</cd>
<cd>
<title rowmerge="F">Title 2</title>
<artist rowmerge="F">Sample 2</artist>
<price rowmerge="T"></price>
<year>1988</year>
</cd>
<cd>
<title rowmerge="F">Title 3</title>
<artist rowmerge="F">Sample 3</artist>
<price rowmerge="F">3</price>
<year>1988</year>
</cd>
<cd>
<title rowmerge="T">Title 4</title>
<artist rowmerge="F">sample 4</artist>
<price rowmerge="T">4</price>
<year >1985</year>
</cd>
<cd>
<title rowmerge="T"></title>
<artist rowmerge="F">Sample 5</artist>
<price rowmerge="T"></price>
<year>1988</year>
</cd>
</catalog>
预期输出:
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<cd>
<title rowmerge="f">Title 1</title>
<artist rowmerge="f">sample 1</artist>
<price rowmerge="f">1</price>
<year >1985</year>
</cd>
<cd>
<title rowmerge="F">Title 2</title>
<artist rowmerge="F">Sample 2</artist>
<price rowmerge="f">1</price>
<year>1988</year>
</cd>
<cd>
<title rowmerge="F">Title 3</title>
<artist rowmerge="F">Sample 3</artist>
<price rowmerge="F">3</price>
<year>1988</year>
</cd>
<cd>
<title rowmerge="F">Title 4</title>
<artist rowmerge="F">sample 4</artist>
<price rowmerge="F">4</price>
<year >1985</year>
</cd>
<cd>
<title rowmerge="F">Title 4</title>
<artist rowmerge="F">Sample 5</artist>
<price rowmerge="F">4</price>
<year>1988</year>
</cd>
</catalog>
如果任何标签 (title/artist/price) 的第一个 cd 中的 rowmerge 属性是 'T',那么我需要将价格值从第一个 cd 复制到下一个 cd。我是 xslt 的新手。
您首先应该阅读 XSLT Identity Template,它会自行将节点从源文档复制到输出。
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
这意味着您只需要为要转换的节点编写模板即可。现在只考虑 price
元素,您正在尝试修改 price
元素,这些元素的 rowmerge
设置为 "T" 且为空。在这种情况下,您想要从第一个最前面的 'cd' 复制 price
。这是这样实现的:
<xsl:template match="price[@rowmerge='T'][not(normalize-space())]">
<price>
<xsl:apply-templates select="@*|node()"/>
<xsl:value-of select="../preceding-sibling::*[1]/price" />
</price>
</xsl:template>
因此,它与身份模板非常相似,但它有额外的 xsl:value-of
语句来从前面的节点复制值。或者更确切地说,来自父 cd
元素的前一个节点的 price
值。
当然,您可以为 cd
的每个可能的子元素重复此模板,但这会产生大量重复编码。最好有一个更通用的模板来涵盖所有情况:
<xsl:template match="*[@rowmerge='T'][not(normalize-space())]">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<xsl:value-of select="../preceding-sibling::*[1]/*[name() = name(current())]" />
</xsl:copy>
</xsl:template>
试试这个 XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="*[@rowmerge='T'][not(normalize-space())]">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<xsl:value-of select="../preceding-sibling::*[1]/*[name() = name(current())]" />
</xsl:copy>
</xsl:template>
<xsl:template match="@rowmerge[. = 'T']">
<xsl:attribute name="rowmerge">F</xsl:attribute>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
请注意,还有一个模板可以将 rowmerge
属性的值从 T
转换为 F
。
编辑:在回答您的评论时,如果您必须回头看一个以上的兄弟姐妹(也就是说,您有两个连续的空元素),请尝试这两个表达式之一
<xsl:value-of select="../preceding-sibling::*[*[name() = name(current())][normalize-space()]][1]/*[name() = name(current())]" />
<xsl:value-of select="(../preceding-sibling::*/*[name() = name(current())][normalize-space()])[last()]" />
编辑 2:如果节点包含的不仅仅是文本,那么要复制所有子元素,您可以使用 xsl:copy-of
而不是 xsl:value-of
。例如...
<xsl:copy-of select="../preceding-sibling::*[1]/*[name() = name(current())]/node()" />
注意在末尾使用 node()
,以确保只复制子节点,而不是 price
(例如)元素本身。
谁能帮我解决下面的 xslt 问题。
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<cd>
<title rowmerge="f">Title 1</title>
<artist rowmerge="f">sample 1</artist>
<price rowmerge="T">1</price>
<year >1985</year>
</cd>
<cd>
<title rowmerge="F">Title 2</title>
<artist rowmerge="F">Sample 2</artist>
<price rowmerge="T"></price>
<year>1988</year>
</cd>
<cd>
<title rowmerge="F">Title 3</title>
<artist rowmerge="F">Sample 3</artist>
<price rowmerge="F">3</price>
<year>1988</year>
</cd>
<cd>
<title rowmerge="T">Title 4</title>
<artist rowmerge="F">sample 4</artist>
<price rowmerge="T">4</price>
<year >1985</year>
</cd>
<cd>
<title rowmerge="T"></title>
<artist rowmerge="F">Sample 5</artist>
<price rowmerge="T"></price>
<year>1988</year>
</cd>
</catalog>
预期输出:
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<cd>
<title rowmerge="f">Title 1</title>
<artist rowmerge="f">sample 1</artist>
<price rowmerge="f">1</price>
<year >1985</year>
</cd>
<cd>
<title rowmerge="F">Title 2</title>
<artist rowmerge="F">Sample 2</artist>
<price rowmerge="f">1</price>
<year>1988</year>
</cd>
<cd>
<title rowmerge="F">Title 3</title>
<artist rowmerge="F">Sample 3</artist>
<price rowmerge="F">3</price>
<year>1988</year>
</cd>
<cd>
<title rowmerge="F">Title 4</title>
<artist rowmerge="F">sample 4</artist>
<price rowmerge="F">4</price>
<year >1985</year>
</cd>
<cd>
<title rowmerge="F">Title 4</title>
<artist rowmerge="F">Sample 5</artist>
<price rowmerge="F">4</price>
<year>1988</year>
</cd>
</catalog>
如果任何标签 (title/artist/price) 的第一个 cd 中的 rowmerge 属性是 'T',那么我需要将价格值从第一个 cd 复制到下一个 cd。我是 xslt 的新手。
您首先应该阅读 XSLT Identity Template,它会自行将节点从源文档复制到输出。
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
这意味着您只需要为要转换的节点编写模板即可。现在只考虑 price
元素,您正在尝试修改 price
元素,这些元素的 rowmerge
设置为 "T" 且为空。在这种情况下,您想要从第一个最前面的 'cd' 复制 price
。这是这样实现的:
<xsl:template match="price[@rowmerge='T'][not(normalize-space())]">
<price>
<xsl:apply-templates select="@*|node()"/>
<xsl:value-of select="../preceding-sibling::*[1]/price" />
</price>
</xsl:template>
因此,它与身份模板非常相似,但它有额外的 xsl:value-of
语句来从前面的节点复制值。或者更确切地说,来自父 cd
元素的前一个节点的 price
值。
当然,您可以为 cd
的每个可能的子元素重复此模板,但这会产生大量重复编码。最好有一个更通用的模板来涵盖所有情况:
<xsl:template match="*[@rowmerge='T'][not(normalize-space())]">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<xsl:value-of select="../preceding-sibling::*[1]/*[name() = name(current())]" />
</xsl:copy>
</xsl:template>
试试这个 XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="*[@rowmerge='T'][not(normalize-space())]">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<xsl:value-of select="../preceding-sibling::*[1]/*[name() = name(current())]" />
</xsl:copy>
</xsl:template>
<xsl:template match="@rowmerge[. = 'T']">
<xsl:attribute name="rowmerge">F</xsl:attribute>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
请注意,还有一个模板可以将 rowmerge
属性的值从 T
转换为 F
。
编辑:在回答您的评论时,如果您必须回头看一个以上的兄弟姐妹(也就是说,您有两个连续的空元素),请尝试这两个表达式之一
<xsl:value-of select="../preceding-sibling::*[*[name() = name(current())][normalize-space()]][1]/*[name() = name(current())]" />
<xsl:value-of select="(../preceding-sibling::*/*[name() = name(current())][normalize-space()])[last()]" />
编辑 2:如果节点包含的不仅仅是文本,那么要复制所有子元素,您可以使用 xsl:copy-of
而不是 xsl:value-of
。例如...
<xsl:copy-of select="../preceding-sibling::*[1]/*[name() = name(current())]/node()" />
注意在末尾使用 node()
,以确保只复制子节点,而不是 price
(例如)元素本身。