[英]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.