使用 xsl:analyze-string 并保留标记(就像在身份转换中一样)
Use xsl:analyze-string and preserve markup (like in an identity transform)
我想处理一个 XML 文件,以便将连续两个换行符之前或之后的任何内容变成一个段落(就像在 LaTeX 中一样)。
这是源文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE letter SYSTEM "../Schema_and_DTD/entities.dtd">
<letter xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Schema_and_DTD/letter.xsd" page_id="940"title="1695-08-17_Faeh_Georg-Bernoulli_Johann_I" catalogue_id="000055848">
<facsimile src=""/> Colendissime ac ornatissime Domine etc.
Colendissimae dominationi Vestrae gratificandi ergo, exactissima diligentia tum in Bibliotheca nostra Conventuali, tum in Bibliopolio mihi commisso perquisivi Chronicon Joannis Vitodurani<ref><i>Die Chronik Johanns von Winterthur (Chronica Iohannis Vitodurani)</i>, herausgegeben von F. Baethgen und C. Brun in: <i>Scriptores rerum Germanicarum</i>, Nova series 3, Berlin 1924.</ref>, sed nihil de eo repertum fuit.<ref>Leibniz hat die Chronik des Johannes von Winterthur später aus Bremen erhalten und in seinem <i>Codex juris gentium diplomaticus</i>, Hanoverae 1693, abgedruckt.</ref> Hisce post mei recommendationem omnem prosperitatem a Bono Deo intime apprecans sum et ero Ornatissimae vestrae dominationis Addictissimus servus P. Georgius Fäch.
Ex Eremo B. V. M.<ref>Einsiedeln</ref> 17. Augusti Anno 1695.
</letter>
我找到了这个解决方案:XSLT - add <p> into text strings instead of \n
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="letter">
<xsl:analyze-string select="." regex="

">
<xsl:non-matching-substring>
<p>
<xsl:value-of select="." disable-output-escaping="yes" />
</p>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
这已经接近我想要的,但问题是 <xsl:value-of select="." disable-output-escaping="yes" />
没有保留任何标记。最后,我只有包含文本内容的段落标签(所有标签都被删除了)。
我想到了身份转换,但不允许我使用 <xsl:apply-templates />
而不是 <xsl:value-of select=".">
。
我要制作的是这样的:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE letter SYSTEM "../Schema_and_DTD/entities.dtd">
<letter xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Schema_and_DTD/letter.xsd" page_id="940" title="1695-08-17_Faeh_Georg-Bernoulli_Johann_I" catalogue_id="000055848">
<p><facsimile src=""/> Colendissime ac ornatissime Domine etc.</p>
<p>Colendissimae dominationi Vestrae gratificandi ergo, exactissima diligentia tum in Bibliotheca nostra Conventuali, tum in Bibliopolio mihi commisso perquisivi Chronicon Joannis Vitodurani<ref><i>Die Chronik Johanns von Winterthur (Chronica Iohannis Vitodurani)</i>, herausgegeben von F. Baethgen und C. Brun in: <i>Scriptores rerum Germanicarum</i>, Nova series 3, Berlin 1924.</ref>, sed nihil de eo repertum fuit.<ref>Leibniz hat die Chronik des Johannes von Winterthur später aus Bremen erhalten und in seinem <i>Codex juris gentium diplomaticus</i>, Hanoverae 1693, abgedruckt.</ref> Hisce post mei recommendationem omnem prosperitatem a Bono Deo intime apprecans sum et ero Ornatissimae vestrae dominationis Addictissimus servus P. Georgius Fäch.</p>
<p>Ex Eremo B. V. M.<ref>Einsiedeln</ref> 17. Augusti Anno 1695.</p>
</letter>
有没有办法获取整个不匹配的子字符串(包括标记)并用段落标记将其包裹起来?
我认为你需要两次通过,一次插入某个元素(我选择了 br
但当然你可以选择任何不会干扰你现有词汇的东西),第二次使用 for-each-group
group-starting-with="br"
:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="@*|node()" mode="#all">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="#current"/>
</xsl:copy>
</xsl:template>
<xsl:template match="letter">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:variable name="letter-with-line-breaks">
<xsl:apply-templates select="." mode="breaks"/>
</xsl:variable>
<xsl:for-each-group select="$letter-with-line-breaks/letter/node()" group-starting-with="br">
<p>
<xsl:apply-templates select="current-group()[not(self::br)]"/>
</p>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="letter//text()" mode="breaks">
<xsl:analyze-string select="." regex=" ">
<xsl:matching-substring>
<br/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
</xsl:transform>
这应该会给你一个想法,我认为你需要一些白色的 space 调整。
这个问题有两种解决方法。
一种是在文本中添加标记,然后使用分组等工具来处理标记指示的结构:这就是 Martin 使用的方法。
第二种方法是将现有标记转换为某种文本注释,然后使用分析字符串来处理文本,然后将文本注释转换回标记。
对于 XSLT 3.0,第二种方法可以通过将 <p>
元素的内容序列化为字符串(使用 fn:serialize()
),然后应用 xsl:analyze-string
,然后解析使用 fn:parse-xml()
.
将结果返回到树中的节点
我想处理一个 XML 文件,以便将连续两个换行符之前或之后的任何内容变成一个段落(就像在 LaTeX 中一样)。
这是源文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE letter SYSTEM "../Schema_and_DTD/entities.dtd">
<letter xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Schema_and_DTD/letter.xsd" page_id="940"title="1695-08-17_Faeh_Georg-Bernoulli_Johann_I" catalogue_id="000055848">
<facsimile src=""/> Colendissime ac ornatissime Domine etc.
Colendissimae dominationi Vestrae gratificandi ergo, exactissima diligentia tum in Bibliotheca nostra Conventuali, tum in Bibliopolio mihi commisso perquisivi Chronicon Joannis Vitodurani<ref><i>Die Chronik Johanns von Winterthur (Chronica Iohannis Vitodurani)</i>, herausgegeben von F. Baethgen und C. Brun in: <i>Scriptores rerum Germanicarum</i>, Nova series 3, Berlin 1924.</ref>, sed nihil de eo repertum fuit.<ref>Leibniz hat die Chronik des Johannes von Winterthur später aus Bremen erhalten und in seinem <i>Codex juris gentium diplomaticus</i>, Hanoverae 1693, abgedruckt.</ref> Hisce post mei recommendationem omnem prosperitatem a Bono Deo intime apprecans sum et ero Ornatissimae vestrae dominationis Addictissimus servus P. Georgius Fäch.
Ex Eremo B. V. M.<ref>Einsiedeln</ref> 17. Augusti Anno 1695.
</letter>
我找到了这个解决方案:XSLT - add <p> into text strings instead of \n
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="letter">
<xsl:analyze-string select="." regex="

">
<xsl:non-matching-substring>
<p>
<xsl:value-of select="." disable-output-escaping="yes" />
</p>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
这已经接近我想要的,但问题是 <xsl:value-of select="." disable-output-escaping="yes" />
没有保留任何标记。最后,我只有包含文本内容的段落标签(所有标签都被删除了)。
我想到了身份转换,但不允许我使用 <xsl:apply-templates />
而不是 <xsl:value-of select=".">
。
我要制作的是这样的:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE letter SYSTEM "../Schema_and_DTD/entities.dtd">
<letter xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Schema_and_DTD/letter.xsd" page_id="940" title="1695-08-17_Faeh_Georg-Bernoulli_Johann_I" catalogue_id="000055848">
<p><facsimile src=""/> Colendissime ac ornatissime Domine etc.</p>
<p>Colendissimae dominationi Vestrae gratificandi ergo, exactissima diligentia tum in Bibliotheca nostra Conventuali, tum in Bibliopolio mihi commisso perquisivi Chronicon Joannis Vitodurani<ref><i>Die Chronik Johanns von Winterthur (Chronica Iohannis Vitodurani)</i>, herausgegeben von F. Baethgen und C. Brun in: <i>Scriptores rerum Germanicarum</i>, Nova series 3, Berlin 1924.</ref>, sed nihil de eo repertum fuit.<ref>Leibniz hat die Chronik des Johannes von Winterthur später aus Bremen erhalten und in seinem <i>Codex juris gentium diplomaticus</i>, Hanoverae 1693, abgedruckt.</ref> Hisce post mei recommendationem omnem prosperitatem a Bono Deo intime apprecans sum et ero Ornatissimae vestrae dominationis Addictissimus servus P. Georgius Fäch.</p>
<p>Ex Eremo B. V. M.<ref>Einsiedeln</ref> 17. Augusti Anno 1695.</p>
</letter>
有没有办法获取整个不匹配的子字符串(包括标记)并用段落标记将其包裹起来?
我认为你需要两次通过,一次插入某个元素(我选择了 br
但当然你可以选择任何不会干扰你现有词汇的东西),第二次使用 for-each-group
group-starting-with="br"
:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="@*|node()" mode="#all">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="#current"/>
</xsl:copy>
</xsl:template>
<xsl:template match="letter">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:variable name="letter-with-line-breaks">
<xsl:apply-templates select="." mode="breaks"/>
</xsl:variable>
<xsl:for-each-group select="$letter-with-line-breaks/letter/node()" group-starting-with="br">
<p>
<xsl:apply-templates select="current-group()[not(self::br)]"/>
</p>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="letter//text()" mode="breaks">
<xsl:analyze-string select="." regex=" ">
<xsl:matching-substring>
<br/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
</xsl:transform>
这应该会给你一个想法,我认为你需要一些白色的 space 调整。
这个问题有两种解决方法。
一种是在文本中添加标记,然后使用分组等工具来处理标记指示的结构:这就是 Martin 使用的方法。
第二种方法是将现有标记转换为某种文本注释,然后使用分析字符串来处理文本,然后将文本注释转换回标记。
对于 XSLT 3.0,第二种方法可以通过将 <p>
元素的内容序列化为字符串(使用 fn:serialize()
),然后应用 xsl:analyze-string
,然后解析使用 fn:parse-xml()
.