XSL 转换 - 如何寻找链接节点
XSL transformation - how to look for linking node
我是 XSL 转换的新手。我正在将以下 XML 转换为另一种 XML 格式:
<root>
<header>
<section id="a1">
<color>red</color>
</section>
<section id="a2">
<color>blue</color>
</section>
</header>
<body>
This is the sample text <reference link="a1">with color red</reference>
and <reference link="a2">with color blue</reference>
</body>
</root>
部分 ID(在 header 中)linked 到引用 link(在 body 中)。我必须在 <color>
节点中寻找颜色 'blue'。如果它可用,那么我必须删除 parent <section>
节点。除此之外,该部分的 'id' 是 "a2"。 body 中相应的引用 link 必须删除。结果:
<root>
<header>
<section id="a1">
<color>red</color>
</section>
</header>
<body>
This is the sample text <reference link="a1">with color red</reference>
and with color blue
</body>
</root>
任何人都可以提供一些关于如何开始的提示吗?
您应该能够获得具有 blue
的部分的 @id
,然后去除 section
和 "unwrap" 以及 reference
。
这里有2个例子。一个在 XSLT 1.0 中,一个在 XSLT 2.0 中。
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="toStrip" select="'blue'"/>
<xsl:variable name="stripRef" select="//section[color=$toStrip]/@id"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="header">
<xsl:copy>
<xsl:apply-templates select="@*|node()[not(self::section[@id=$stripRef])]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="reference">
<xsl:choose>
<xsl:when test="@link=$stripRef">
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
XSLT 2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="toStrip" select="'blue'"/>
<xsl:variable name="stripRef" select="//section[color=$toStrip]/@id"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="section[@id=$stripRef]"/>
<xsl:template match="reference[@link=$stripRef]">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
根据评论进行编辑
这是处理多个 ID 的一种方法。由于 toStrip
参数不能是序列,我们需要添加一个字符来分隔值。在这个例子中,我使用了 |
。这样一来,在将 a1
与 a10
.
进行比较时,contains()
就不会成立
此外,XSLT 1.0 只会 return stripRef
变量 select 中的第一个 @id
。为了获取所有 ID,我添加了一个 xsl:for-each
。您也可以通过使用模式对 xsl:apply-templates
执行此操作。
这是更新后的 XSLT:
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="toStrip" select="'|blue|orange|'"/>
<xsl:variable name="stripRef">
<xsl:text>|</xsl:text>
<xsl:for-each select="//section[color[contains($toStrip,concat('|',.,'|'))]]/@id">
<xsl:value-of select="concat(.,'|')"/>
</xsl:for-each>
</xsl:variable>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="header">
<xsl:copy>
<xsl:apply-templates select="@*|node()[not(self::section[contains($stripRef,concat('|',@id,'|'))])]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="reference">
<xsl:message>contains(<xsl:value-of select="$stripRef"/>,<xsl:value-of select="concat('|',@link,'|')"/>)</xsl:message>
<xsl:choose>
<xsl:when test="contains($stripRef,concat('|',@link,'|'))">
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
要在 XSLT 2.0 中做同样的事情,您只需将 toStrip
参数更改为一个序列:
<xsl:param name="toStrip" select="('blue','orange')"/>
我是 XSL 转换的新手。我正在将以下 XML 转换为另一种 XML 格式:
<root>
<header>
<section id="a1">
<color>red</color>
</section>
<section id="a2">
<color>blue</color>
</section>
</header>
<body>
This is the sample text <reference link="a1">with color red</reference>
and <reference link="a2">with color blue</reference>
</body>
</root>
部分 ID(在 header 中)linked 到引用 link(在 body 中)。我必须在 <color>
节点中寻找颜色 'blue'。如果它可用,那么我必须删除 parent <section>
节点。除此之外,该部分的 'id' 是 "a2"。 body 中相应的引用 link 必须删除。结果:
<root>
<header>
<section id="a1">
<color>red</color>
</section>
</header>
<body>
This is the sample text <reference link="a1">with color red</reference>
and with color blue
</body>
</root>
任何人都可以提供一些关于如何开始的提示吗?
您应该能够获得具有 blue
的部分的 @id
,然后去除 section
和 "unwrap" 以及 reference
。
这里有2个例子。一个在 XSLT 1.0 中,一个在 XSLT 2.0 中。
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="toStrip" select="'blue'"/>
<xsl:variable name="stripRef" select="//section[color=$toStrip]/@id"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="header">
<xsl:copy>
<xsl:apply-templates select="@*|node()[not(self::section[@id=$stripRef])]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="reference">
<xsl:choose>
<xsl:when test="@link=$stripRef">
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
XSLT 2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="toStrip" select="'blue'"/>
<xsl:variable name="stripRef" select="//section[color=$toStrip]/@id"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="section[@id=$stripRef]"/>
<xsl:template match="reference[@link=$stripRef]">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
根据评论进行编辑
这是处理多个 ID 的一种方法。由于 toStrip
参数不能是序列,我们需要添加一个字符来分隔值。在这个例子中,我使用了 |
。这样一来,在将 a1
与 a10
.
contains()
就不会成立
此外,XSLT 1.0 只会 return stripRef
变量 select 中的第一个 @id
。为了获取所有 ID,我添加了一个 xsl:for-each
。您也可以通过使用模式对 xsl:apply-templates
执行此操作。
这是更新后的 XSLT:
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="toStrip" select="'|blue|orange|'"/>
<xsl:variable name="stripRef">
<xsl:text>|</xsl:text>
<xsl:for-each select="//section[color[contains($toStrip,concat('|',.,'|'))]]/@id">
<xsl:value-of select="concat(.,'|')"/>
</xsl:for-each>
</xsl:variable>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="header">
<xsl:copy>
<xsl:apply-templates select="@*|node()[not(self::section[contains($stripRef,concat('|',@id,'|'))])]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="reference">
<xsl:message>contains(<xsl:value-of select="$stripRef"/>,<xsl:value-of select="concat('|',@link,'|')"/>)</xsl:message>
<xsl:choose>
<xsl:when test="contains($stripRef,concat('|',@link,'|'))">
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
要在 XSLT 2.0 中做同样的事情,您只需将 toStrip
参数更改为一个序列:
<xsl:param name="toStrip" select="('blue','orange')"/>