在XML文档中,我打算在两个自闭元素之间插入元素。请考虑以下示例:
<body>
<p>Lorem ipsum dolor sit amet,
<lb/>consectetur adipisici elit,
<lb/>sed eiusmod tempor incidunt
<lb/>ut labore et dolore magna aliqua.
</p>
<p>Ut enim ad minim veniam,
<lb/>quis nostrud exercitation ullamco
<lb/>laboris nisi ut aliquid
<lb/>ex ea commodi consequat.
</p>
</body>
所以有像段落(p)和换行符(lb)这样的结构。我的目标是将线条放入元素中。所以我想实现以下转换结果(或类似):
<body>
<p>
<l>Lorem ipsum dolor sit amet,</l>
<l>consectetur adipisici elit,</l>
<l>sed eiusmod tempor incidunt</l>
<l>ut labore et dolore magna aliqua.</l>
</p>
<p>
<l>Ut enim ad minim veniam,</l>
<l>quis nostrud exercitation ullamco</l>
<l>laboris nisi ut aliquid</l>
<l>ex ea commodi consequat.</l>
</p>
</body>
这实际上是否可以使用XSLT?这似乎不是典型的应用程序,因为我还没有找到方法。我将不胜感激任何帮助。
编辑: 这是一个更复杂的问题变体,它增加了: (1)突出显示,重叠的段落(hi)和 (2)重叠的“选择”元素,其中只需要保留“sic”元素。
<body>
<p>Lorem ipsum dolor sit amet,
<lb/>consectetur adipisici elit,
<lb/>sed eiusmod tempor <hi>incidunt
<lb/>ut labore</hi> et dolore magna aliqua.
</p>
<p>Ut enim ad minim <choice>
<sic>venima, <lb/>quis noster</sic>
<corr>veniam, quis nostrud</corr>
</choice> exercitation ullamco
<lb/>laboris nisi ut aliquid
<lb/>ex ea commodi consequat.
</p>
</body>
例如,期望的输出将是 (1)行号,和 (2)@cont属性,表示分割元素的延续。
<body>
<p>
<l n="1">Lorem ipsum dolor sit amet,</l>
<l n="2">consectetur adipisici elit,</l>
<l n="3">sed eiusmod tempor <hi cont="true">incidunt</hi></l>
<l n="4"><hi cont="false">ut labore</hi> et dolore magna aliqua.</l>
</p>
<p>
<l n="5">Ut enim ad minim <sic cont="true">venima,</sic></l>
<l n="6"><sic cont="false">quis noster</sic> exercitation ullamco</l>
<l n="7">laboris nisi ut aliquid</l>
<l n="8">ex ea commodi consequat.</l>
</p>
</body>
这实际上涵盖了我遇到的最糟糕的情况。感谢您的帮助!
答案 0 :(得分:3)
这是一个更复杂的问题变体,它增加了:(1) 突出显示,重叠的段落(hi)和(2)重叠的选择&#34; 元素,其中只有&#34; sic&#34;元素需要保留。
嗯,这很有意思 - 尽管对于单个SO问题可能太过分了。无论如何,我无法立刻找到办法完成所有这些工作。以下样式表使用两个过程返回几乎您所请求的结果:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="first-pass">
<xsl:apply-templates select="/*" mode="first-pass"/>
</xsl:variable>
<!-- identity transform -->
<xsl:template match="@*|node()" mode="#all">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="#current"/>
</xsl:copy>
</xsl:template>
<!-- FIRST-PASS TEMPLATES -->
<!-- remove choice wrapper, preserve only sic content -->
<xsl:template match="choice" mode="first-pass">
<xsl:apply-templates select="sic" mode="first-pass"/>
</xsl:template>
<!-- split hi and sic accross lb -->
<xsl:template match="hi | sic" mode="first-pass">
<xsl:variable name="elem-name" select="local-name()" />
<xsl:for-each-group select="text()" group-by="generate-id(preceding-sibling::lb[1])">
<xsl:element name="{$elem-name}">
<xsl:attribute name="cont" select="position()!=last()"/>
<xsl:apply-templates select="current-group()" mode="first-pass"/>
</xsl:element>
<xsl:if test="position()!=last()">
<lb/>
</xsl:if>
</xsl:for-each-group>
</xsl:template>
<!-- OUTPUT -->
<xsl:template match="/">
<xsl:apply-templates select="$first-pass/*"/>
</xsl:template>
<!-- create a line element for each group separated by lb -->
<xsl:template match="*[lb]">
<xsl:copy>
<xsl:for-each-group select="node()" group-ending-with="lb">
<l n="{position()}">
<xsl:apply-templates select="current-group()"/>
</l>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<!-- suppress lb -->
<xsl:template match="lb"/>
</xsl:stylesheet>
<强>结果强>:
<?xml version="1.0" encoding="UTF-8"?>
<body>
<p>
<l n="1">Lorem ipsum dolor sit amet,
</l>
<l n="2">consectetur adipisici elit,
</l>
<l n="3">sed eiusmod tempor <hi cont="true">incidunt
</hi>
</l>
<l n="4">
<hi cont="false">ut labore</hi> et dolore magna aliqua.
</l>
</p>
<p>
<l n="1">Ut enim ad minim <sic cont="true">venima, </sic>
</l>
<l n="2">
<sic cont="false">quis noster</sic> exercitation ullamco
</l>
<l n="3">laboris nisi ut aliquid
</l>
<l n="4">ex ea commodi consequat.
</l>
</p>
</body>
答案 1 :(得分:2)
如果行之间始终存在lb
元素,则以下操作将会执行,因为由子元素分隔的文本内容最终会出现在单独的文本节点中。
XSLT样式表
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="body">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="p">
<xsl:copy>
<xsl:for-each select="text()">
<l>
<xsl:value-of select="normalize-space(.)"/>
</l>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
XML输出
<?xml version="1.0" encoding="UTF-8"?>
<body>
<p>
<l>Lorem ipsum dolor sit amet,</l>
<l>consectetur adipisici elit,</l>
<l>sed eiusmod tempor incidunt</l>
<l>ut labore et dolore magna aliqua.</l>
</p>
<p>
<l>Ut enim ad minim veniam,</l>
<l>quis nostrud exercitation ullamco</l>
<l>laboris nisi ut aliquid</l>
<l>ex ea commodi consequat.</l>
</p>
</body>