XSLT,类似于`flatmap`的操作
XSLT, `flatmap` like operation
我目前正在学习 XSLT,但它对我来说仍然太模糊,无法做任何有用的事情。你能给我一个提示(或者更好的,样式表)来转换所有这样的元素
<match target="font">
<test name="family" compare="eq">
<string>Foo</string>
<string>Bar</string>
<string>Baz</string>
</test>
<edit name="embeddedbitmap" mode="assign"><bool>false</bool></edit>
</match>
进入这个?
<match target="font">
<test name="family" compare="eq">
<string>Foo</string>
</test>
<edit name="embeddedbitmap" mode="assign"><bool>false</bool></edit>
</match>
<match target="font">
<test name="family" compare="eq">
<string>Bar</string>
</test>
<edit name="embeddedbitmap" mode="assign"><bool>false</bool></edit>
</match>
<match target="font">
<test name="family" compare="eq">
<string>Baz</string>
</test>
<edit name="embeddedbitmap" mode="assign"><bool>false</bool></edit>
</match>
谢谢。
编辑:我正在学习并尝试使用 XSLT 1。
您没有指定您使用的 XSLT 版本,所以我假设是 XSLT1。还,
您的示例输出缺少根元素,这意味着它的格式不正确 XML,因此我添加了一个。
这是一种选择:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output method="xml" indent="yes"/>
<!-- Match the root node of this document -->
<xsl:template match="/">
<!-- Create the <root> element so that the document has a root element. -->
<root>
<xsl:apply-templates/>
</root>
</xsl:template>
<!-- Match the <match> element. -->
<xsl:template match="match">
<xsl:apply-templates select="test/string" mode="match"/>
</xsl:template>
<xsl:template match="string" mode="match">
<!--
Apply the closest ancestor <match> element of the current <string> element.
-->
<xsl:apply-templates select="ancestor::match[1]" mode="match">
<!--
Pass the current string element as a parameter to the matched template.
-->
<xsl:with-param name="string" select="."/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="match" mode="match">
<!--
If you're using XSLT2, you can use a tunnel parameter, in which case you
don't have to specify the parameter here.
-->
<xsl:param name="string"/>
<!-- Copy this <match> element into the output as is. -->
<xsl:copy>
<!-- Apply the attributes of this element with the default mode. -->
<xsl:apply-templates select="@*"/>
<!--
Apply the child nodes (element or text) with the "match" mode. Pass the
<string> element we passed as a parameter earlier on to the applied
templates.
-->
<xsl:apply-templates select="node()" mode="match">
<xsl:with-param name="string" select="$string"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="test" mode="match">
<!--
Remember, this parameter points to <string>Foo</string>,
<string>Bar</string>, or <string>Baz</string>.
-->
<xsl:param name="string"/>
<!-- Copy this element as is. -->
<xsl:copy>
<!-- Copy its attributes as is, too. -->
<xsl:apply-templates select="@*"/>
<!--
Don't copy any of the child elements as is: rather, create a copy of the
<string> element we passed as a parameter here.
-->
<xsl:copy-of select="$string"/>
</xsl:copy>
</xsl:template>
<!--
For every other attribute, element or text node that is applied with the
"match" mode, defer to the default mode. In this case, that means deferring
to the identity transform template (see below).
-->
<xsl:template match="@* | node()" mode="match">
<xsl:apply-templates select="."/>
</xsl:template>
<!--
Identity transform: every attribute or element matched by this template into
the output as is.
-->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
输出:
<root>
<match target="font">
<test name="family" compare="eq">
<string>Foo</string>
</test>
<edit name="embeddedbitmap" mode="assign">
<bool>false</bool>
</edit>
</match>
<match target="font">
<test name="family" compare="eq">
<string>Bar</string>
</test>
<edit name="embeddedbitmap" mode="assign">
<bool>false</bool>
</edit>
</match>
<match target="font">
<test name="family" compare="eq">
<string>Baz</string>
</test>
<edit name="embeddedbitmap" mode="assign">
<bool>false</bool>
</edit>
</match>
</root>
我目前正在学习 XSLT,但它对我来说仍然太模糊,无法做任何有用的事情。你能给我一个提示(或者更好的,样式表)来转换所有这样的元素
<match target="font">
<test name="family" compare="eq">
<string>Foo</string>
<string>Bar</string>
<string>Baz</string>
</test>
<edit name="embeddedbitmap" mode="assign"><bool>false</bool></edit>
</match>
进入这个?
<match target="font">
<test name="family" compare="eq">
<string>Foo</string>
</test>
<edit name="embeddedbitmap" mode="assign"><bool>false</bool></edit>
</match>
<match target="font">
<test name="family" compare="eq">
<string>Bar</string>
</test>
<edit name="embeddedbitmap" mode="assign"><bool>false</bool></edit>
</match>
<match target="font">
<test name="family" compare="eq">
<string>Baz</string>
</test>
<edit name="embeddedbitmap" mode="assign"><bool>false</bool></edit>
</match>
谢谢。
编辑:我正在学习并尝试使用 XSLT 1。
您没有指定您使用的 XSLT 版本,所以我假设是 XSLT1。还, 您的示例输出缺少根元素,这意味着它的格式不正确 XML,因此我添加了一个。
这是一种选择:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output method="xml" indent="yes"/>
<!-- Match the root node of this document -->
<xsl:template match="/">
<!-- Create the <root> element so that the document has a root element. -->
<root>
<xsl:apply-templates/>
</root>
</xsl:template>
<!-- Match the <match> element. -->
<xsl:template match="match">
<xsl:apply-templates select="test/string" mode="match"/>
</xsl:template>
<xsl:template match="string" mode="match">
<!--
Apply the closest ancestor <match> element of the current <string> element.
-->
<xsl:apply-templates select="ancestor::match[1]" mode="match">
<!--
Pass the current string element as a parameter to the matched template.
-->
<xsl:with-param name="string" select="."/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="match" mode="match">
<!--
If you're using XSLT2, you can use a tunnel parameter, in which case you
don't have to specify the parameter here.
-->
<xsl:param name="string"/>
<!-- Copy this <match> element into the output as is. -->
<xsl:copy>
<!-- Apply the attributes of this element with the default mode. -->
<xsl:apply-templates select="@*"/>
<!--
Apply the child nodes (element or text) with the "match" mode. Pass the
<string> element we passed as a parameter earlier on to the applied
templates.
-->
<xsl:apply-templates select="node()" mode="match">
<xsl:with-param name="string" select="$string"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="test" mode="match">
<!--
Remember, this parameter points to <string>Foo</string>,
<string>Bar</string>, or <string>Baz</string>.
-->
<xsl:param name="string"/>
<!-- Copy this element as is. -->
<xsl:copy>
<!-- Copy its attributes as is, too. -->
<xsl:apply-templates select="@*"/>
<!--
Don't copy any of the child elements as is: rather, create a copy of the
<string> element we passed as a parameter here.
-->
<xsl:copy-of select="$string"/>
</xsl:copy>
</xsl:template>
<!--
For every other attribute, element or text node that is applied with the
"match" mode, defer to the default mode. In this case, that means deferring
to the identity transform template (see below).
-->
<xsl:template match="@* | node()" mode="match">
<xsl:apply-templates select="."/>
</xsl:template>
<!--
Identity transform: every attribute or element matched by this template into
the output as is.
-->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
输出:
<root>
<match target="font">
<test name="family" compare="eq">
<string>Foo</string>
</test>
<edit name="embeddedbitmap" mode="assign">
<bool>false</bool>
</edit>
</match>
<match target="font">
<test name="family" compare="eq">
<string>Bar</string>
</test>
<edit name="embeddedbitmap" mode="assign">
<bool>false</bool>
</edit>
</match>
<match target="font">
<test name="family" compare="eq">
<string>Baz</string>
</test>
<edit name="embeddedbitmap" mode="assign">
<bool>false</bool>
</edit>
</match>
</root>