XSLT 节点相等匹配一切
XSLT node equality matching everything
我有一个 XML 文件,例如:
<?xml version="1.0" encoding="ISO-8859-1"?>
<list>
<report file="onefile.xml" oneAttr="2123as"></report>
<report file="myfile.xml" oneAttr="blabla"></report>
<report file="myfile.xml" oneAttr="2123as"></report>
<report file="another.xml" oneAttr="2123as"></report>
</list> <!-- changed by edit -->
而且我需要一个样式表,它可以在 @file="myfile.xml"
的最后一场比赛之后添加一个新的报告元素。
到目前为止我得到了什么:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="/list">
<list>
<xsl:variable name="insertAfter" select="report[@file='myfile.xml'][last()]"/>
<xsl:for-each select="report">
<xsl:copy-of select="."/>
<xsl:text>
</xsl:text>
<xsl:if test="current() = $insertAfter">
<report file="newFile.xml"></report>
</xsl:if>
<xsl:text>
</xsl:text>
</xsl:for-each>
</list>
</xsl:template>
上面的 XSLT 不工作,相等比较似乎没有按预期工作并且正在匹配所有报告,因此每次都添加新的节点元素。我假设它可能不检查属性的相等性,而只检查其中为空的文本。
我知道在 XSLT 2.0 中有这个 "eq" 运算符,它可能正在做我想要的,但我想坚持使用 XSLT 1.0。
有什么解决方案的建议吗?
您的口头描述 'last match of @file="myfile.xml"' 翻译成
<xsl:template match="report[@file = 'myfile.xml'][last()]">
<xsl:call-template name="identity"/>
<report file="newFile.xml"></report>
</xsl:template>
所以你似乎只需要
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="report[@file = 'myfile.xml'][last()]">
<xsl:call-template name="identity"/>
<report file="newFile.xml"></report>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/gWmuiJU
存在 XSLT 2 中的节点身份检查,但将使用 is
运算符而不是 eq
来完成。但是你也不需要它。
您可以通过使用 generate-id(...)
function 创建 last()
节点的唯一 ID 并匹配它来实现:
<xsl:template match="/list">
<list>
<xsl:variable name="insertAfter" select="generate-id(report[@file='myfile.xml'][last()])"/>
<xsl:for-each select="report">
<xsl:copy-of select="."/>
<xsl:text>
</xsl:text>
<xsl:if test="generate-id(current()) = $insertAfter">
<report file="newFile.xml"></report>
</xsl:if>
<xsl:text>
</xsl:text>
</xsl:for-each>
</list>
</xsl:template>
输出:
<?xml version="1.0"?>
<list>
<report file="onefile.xml" oneAttr="2123as"/>
<report file="myfile.xml" oneAttr="blabla"/>
<report file="myfile.xml" oneAttr="2123as"/>
<report file="newFile.xml"/>
<report file="another.xml" oneAttr="2123as"/>
</list>
我有一个 XML 文件,例如:
<?xml version="1.0" encoding="ISO-8859-1"?>
<list>
<report file="onefile.xml" oneAttr="2123as"></report>
<report file="myfile.xml" oneAttr="blabla"></report>
<report file="myfile.xml" oneAttr="2123as"></report>
<report file="another.xml" oneAttr="2123as"></report>
</list> <!-- changed by edit -->
而且我需要一个样式表,它可以在 @file="myfile.xml"
的最后一场比赛之后添加一个新的报告元素。
到目前为止我得到了什么:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="/list">
<list>
<xsl:variable name="insertAfter" select="report[@file='myfile.xml'][last()]"/>
<xsl:for-each select="report">
<xsl:copy-of select="."/>
<xsl:text>
</xsl:text>
<xsl:if test="current() = $insertAfter">
<report file="newFile.xml"></report>
</xsl:if>
<xsl:text>
</xsl:text>
</xsl:for-each>
</list>
</xsl:template>
上面的 XSLT 不工作,相等比较似乎没有按预期工作并且正在匹配所有报告,因此每次都添加新的节点元素。我假设它可能不检查属性的相等性,而只检查其中为空的文本。
我知道在 XSLT 2.0 中有这个 "eq" 运算符,它可能正在做我想要的,但我想坚持使用 XSLT 1.0。
有什么解决方案的建议吗?
您的口头描述 'last match of @file="myfile.xml"' 翻译成
<xsl:template match="report[@file = 'myfile.xml'][last()]">
<xsl:call-template name="identity"/>
<report file="newFile.xml"></report>
</xsl:template>
所以你似乎只需要
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="report[@file = 'myfile.xml'][last()]">
<xsl:call-template name="identity"/>
<report file="newFile.xml"></report>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/gWmuiJU
存在 XSLT 2 中的节点身份检查,但将使用 is
运算符而不是 eq
来完成。但是你也不需要它。
您可以通过使用 generate-id(...)
function 创建 last()
节点的唯一 ID 并匹配它来实现:
<xsl:template match="/list">
<list>
<xsl:variable name="insertAfter" select="generate-id(report[@file='myfile.xml'][last()])"/>
<xsl:for-each select="report">
<xsl:copy-of select="."/>
<xsl:text>
</xsl:text>
<xsl:if test="generate-id(current()) = $insertAfter">
<report file="newFile.xml"></report>
</xsl:if>
<xsl:text>
</xsl:text>
</xsl:for-each>
</list>
</xsl:template>
输出:
<?xml version="1.0"?>
<list>
<report file="onefile.xml" oneAttr="2123as"/>
<report file="myfile.xml" oneAttr="blabla"/>
<report file="myfile.xml" oneAttr="2123as"/>
<report file="newFile.xml"/>
<report file="another.xml" oneAttr="2123as"/>
</list>