[英]Copy text and replace character in XSL
我正在将 DITA 文档转换为简化的、基于格式的 XML 以用作导入到 Adobe InDesign 中。 我的转换非常顺利,除了一个元素省略了 output 中的文本。该元素是codeblock
。 当我根本没有指定它的模板时,元素和任何子元素都会传递到新的 XML 文档,但不会传递任何文本。 该元素应该与文本和子元素一起传递,就像我的文档中未定义特定模板的所有其他元素一样。 XSL 样式表中没有任何其他地方指定codeblock
或其任何属性。 我完全被难住了,无法弄清楚这里发生了什么。
还值得注意的是,一些内联元素( cmdname
、 parmname
、 userinput
等)在 output 上被转换为bold
。下游 XML 用于格式化,不需要知道语义上下文。
这就是我想要通过的:
<codeblock>This is the first line of my code block.
This is my second line to prove that line feeds are preserved.
This line proves that <parmname>child elements</parmname> are passed through.</codeblock>
没有为codeblock
定义模板,这就是我得到的结果:
<codeblock><bold/></codeblock>
我想要的实际结果是:
<codeblock>This is the first line of my code block.
This is my second line to prove that line feeds are preserved.
This line proves that <bold>child elements</bold> are passed through.</codeblock>
我需要用字符实体替换换行符,因为 InDesign 会将任何不以元素开头的新行视为分栏符。 我的目标是简单地将换行符替换为

使用以下模板:
<xsl:template match="codeblock//text()">
<xsl:analyze-string select="." regex="( )">
<xsl:matching-substring>
<xsl:choose>
<xsl:when test="regex-group(1)">
</xsl:when>
</xsl:choose>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:template>
但我得到的是:
<codeblock>
<bold/>
</codeblock>
我终于能够使用此模板传递文本:
<xsl:template match="codeblock//text()">
<xsl:copy/>
</xsl:template>
成功,顺带一提。 我必须在代码块下的任何级别进行匹配,因此它也包含子 parmname 元素的文本。 由于我能够使用<xsl:copy>
成功传递它,因此我尝试在替换换行符的同时传递文本:
<xsl:template match="codeblock//text()">
<xsl:copy>
<xsl:analyze-string select="." regex="( )">
<xsl:matching-substring>
<xsl:choose>
<xsl:when test="regex-group(1)">
</xsl:when>
</xsl:choose>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:copy>
</xsl:template>
但现在它不会取代新的换行符。 相反,我得到了这个(这是我希望在没有定义任何模板的情况下得到的):
<codeblock>This is the first line of my code block.
This is my second line to prove that line feeds are preserved.
This line proves that <bold>child elements</bold> are passed through.</codeblock>
我知道这是一个很长而且有点令人费解的问题。 我只是觉得如果我能解决为什么它不首先传递文本的问题,那么 rest 将相当简单。 很抱歉,我无法提供我的源代码 XML 或 XSL,因为它处于 NDA 之下,但如果您需要更多,请告诉我,我会尽力提供。 (我的 XSL 样式表由 12 个不同的文件组成,所以我无法提供所有的文件,即使是通用的。)
任何关于我可能在我的样式表中寻找的内容的建议都可以解释为什么文本会出现,或者任何关于如何强制它通过的建议,就像我对<xsl:copy>
所做的那样,同时仍然替换换行符,将不胜感激!
编辑添加:我想到它没有进行替换的原因是它看起来实际上不是换行符。 它更像是代码中的新行,而不是文本中的换行符(或硬回车)。 我想我可能需要在插入

时规范化文本。 每行末尾的字符。 仍在调查中,但欢迎提出建议!
编辑更新:感谢XSLT 中的 How to detect line breaks 帖子,我已经接近了,但仍然不是我需要的地方。 使用此代码,我能够检测 XML 中的换行符并为 InDesign 插入换行符:
<xsl:template match="codeblock//text()">
<xsl:for-each select="tokenize(., '\n?')[.]">
<xsl:sequence select="."/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
但是,它还会在字符串末尾插入换行符,即使它不是行尾也是如此。 例如,我现在得到:
<codeblock>This is the first line of my code block.
This is my second line to prove that line feeds are preserved.
This line proves that 
<bold>child elements
</bold> are passed through.
</codeblock>
我不希望“粗体”开始和结束标记或codeblock
结束标记前面的换行符。 我只是想让它出现在有实际换行的地方。 我尝试替换\r
但只是忽略了新行并将其放在标签前面。 有谁知道另一个可以在这里工作的转义字符?
一个很长的问题 - 但仍然不清楚你到底在问什么(也没有可重现的例子)。
如果 - 看起来 - 你想在codeblock
元素下的所有文本节点中用行分隔符替换换行符,你应该能够简单地做到:
<xsl:template match="codeblock//text()">
<xsl:value-of select="translate(., ' ', '
')" />
</xsl:template>
如果这不起作用,那么要么您有一个覆盖模板,要么文本不包含换行符。 您可以通过将模板更改为以下内容来测试第一种情况:
<xsl:template match="codeblock//text()">BINGO</xsl:template>
并观察结果,看是否所有目标文本节点都更改为“BINGO”。 要测试第二种情况,您可以使用string-to-codepoints()
function 逐个字符地分析文本。
您的模板缺少xsl:non-matching-substring
来处理文本节点的不匹配部分。
<xsl:template match="codeblock//text()">
<xsl:analyze-string select="." regex="\n">
<xsl:matching-substring>
<xsl:text>
</xsl:text>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
但是, michael.hor257k 的答案更简单,因为您不需要xsl:analyze-string
来替换所有子字符串。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.