我没有使用xslt的经验,但我正在尝试通过调整一些代码来学习。
在XML中,我有多次出现不同的id
和rid
,如下所示:
<fn id="TFN01t1"><label>*</label><p>Some text.</p></fn>
<fn id="TFN02t1"><label>**</label><p>Some text.</p></fn>
...
<p>This is a reference<xref ref-type="table-fn" rid="TFN01t1">*</xref></p>
<p>This is another reference<xref ref-type="table-fn" rid="TFN02t1">*</xref></p>
我需要在fn标签的ID属性中执行以下正则表达式,在任何外部参照标记的RID属性中执行 ,并交换数字部分,以便TFN02t1变为TFN1t02。
"find": TFN([0-9]+)t([1-9]+)
"replace": TFN\2t\1
我找到this SO answer about fn:replace但不知道如何使用它。
有什么想法吗?
答案 0 :(得分:2)
如果你可以不使用正则表达式,你也可以使用这个简单的XSLT1兼容解决方案:
<root>
<fn id="TFN01t1"><label>*</label><p>Some text.</p></fn>
<fn id="TFN02t1"><label>**</label><p>Some text.</p></fn>
<p>This is a reference<xref ref-type="table-fn" rid="TFN01t1">*</xref></p>
<p>This is another reference<xref ref-type="table-fn" rid="TFN02t1">*</xref></p>
</root>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8"/>
<xsl:template match="fn/@id | xref[@ref-type = 'table']/@rid">
<xsl:variable name="after-tfn" select="substring-after(., 'TFN')"/>
<xsl:variable name="n1" select="substring-before($after-tfn, 't')"/>
<xsl:variable name="n2" select="substring-after($after-tfn, 't')"/>
<xsl:attribute name="{local-name()}">
<xsl:value-of select="concat('TFN', $n2, 't', $n1)"/>
</xsl:attribute>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="utf-8"?>
<root>
<fn id="TFN1t01"><label>*</label><p>Some text.</p></fn>
<fn id="TFN1t02"><label>**</label><p>Some text.</p></fn>
<p>This is a reference<xref ref-type="table-fn" rid="TFN1t01">*</xref></p>
<p>This is another reference<xref ref-type="table-fn" rid="TFN1t02">*</xref></p>
</root>
如果你可以使用XSLT2并想使用正则表达式,这个样式表应该会得到相同的结果:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8"/>
<xsl:template match="fn/@id | xref/@rid">
<xsl:attribute name="{local-name(.)}">
<xsl:analyze-string select="." regex="TFN([0-9]+)t([1-9]+)">
<xsl:matching-substring>
<xsl:value-of select="concat('TFN', regex-group(2), 't', regex-group(1))"/>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:attribute>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
有关XSLT2中正则表达式支持的更多信息,请参阅Regular Expression Matching in XSLT 2。
答案 1 :(得分:2)
如果您尝试通过调整现有代码来尝试这样做,那么在没有能够看到现有代码的情况下帮助您有点困难。
您需要一个与相关节点匹配的模板规则,例如
<xsl:template match="fn/@id | xref/@rid">
<xsl:attribute name="{name()}" select="replace('.', 'TFN([0-9]+)t([1-9]+)',
'TFN$2t$1')"/>
</xsl:template>
然后你需要确保样式表中的某个地方对xsl:apply-templates进行调用,选择这些属性节点进行处理,因为如果没有这个,你的模板规则永远不会被调用。