编辑:对于那些将来会遇到这种情况的人来说,这是一个写得不好的问题。这不是我追求的。 This Question也可能对您有用。
所以,过去几天我一直试图在我的XSLT
上努力。我对它非常不熟悉,过去大部分时间都使用XQuery
来转换我的XML。我陷入了一个相当简单的问题,但环顾四周我还没有找到一个明确的解决方案。简单地说,我想根据孩子的不同将一些元素分成两部分。
例如,如果我的XML如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<p>
Bacon ipsum dolor sit amet bacon chuck pastrami swine pork rump, shoulder beef ribs doner tri-tip
tongue. Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin pastrami t-
bone. Sirloin turducken short ribs t-bone andouille strip steak pork loin corned beef hamburger
bacon filet mignon pork chop tail.
<note.ref id="0001"><super>1</super></note.ref>
<note id="0001">
<p>
You may need to consult a latin butcher. Good Luck.
</p>
</note>
Pork loin ribeye bacon pastrami drumstick sirloin, shoulder pig jowl. Salami brisket rump ham, tail
hamburger strip steak pig ham hock short ribs jerky shank beef spare ribs. Capicola short ribs swine
beef meatball jowl pork belly. Doner leberkas short ribs, flank chuck pancetta bresaola bacon ham
hock pork hamburger fatback.
</p>
</root>
在我运行xsl
后,我留下了以下内容:
<html>
<body>
<p>
Bacon ipsum dolor sit amet bacon chuck pastrami swine pork rump, shoulder beef ribs doner tri-tip
tongue. Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin pastrami t-
bone. Sirloin turducken short ribs t-bone andouille strip steak pork loin corned beef hamburger
bacon filet mignon pork chop tail.
<span class="noteRef" id="0001"><sup>1</sup></span>
<div id="note-0001">
<p>
You may need to consult a latin butcher. Good Luck.
</p>
</div>
Pork loin ribeye bacon pastrami drumstick sirloin, shoulder pig jowl. Salami brisket rump ham, tail
hamburger strip steak pig ham hock short ribs jerky shank beef spare ribs. Capicola short ribs swine
beef meatball jowl pork belly. Doner leberkas short ribs, flank chuck pancetta bresaola bacon ham
hock pork hamburger fatback.
</p>
</body>
</html>
问题显然是HTML
<p>
作为一个孩子不能拥有<div>
,让另一个<p>
作为孙子。这只是无效的。浏览器(例如chrome)可以使第一个段落在到达<div>
时结束,在适当的情况下包装自己的<p>
中的注释,但将注释保留在注释之后。因此,应用于<p>
的任何CSS都将无法应用。
如何根据元素后代将一个<p>
元素拆分为两个?
所需的输出
<html>
<body>
<p>
Bacon ipsum dolor sit amet bacon chuck pastrami swine pork rump, shoulder beef ribs doner tri-tip
tongue. Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin pastrami t-
bone. Sirloin turducken short ribs t-bone andouille strip steak pork loin corned beef hamburger
bacon filet mignon pork chop tail.
<span class="noteRef" id="0001"><sup>1</sup></span><
</p>
<div id="note-0001">
<p>
You may need to consult a latin butcher. Good Luck.
</p>
</div>
<p>
Pork loin ribeye bacon pastrami drumstick sirloin, shoulder pig jowl. Salami brisket rump ham, tail
hamburger strip steak pig ham hock short ribs jerky shank beef spare ribs. Capicola short ribs swine
beef meatball jowl pork belly. Doner leberkas short ribs, flank chuck pancetta bresaola bacon ham
hock pork hamburger fatback.
</p>
</body>
</html>
我略微抽象了我的问题,所以我尝试的以下XSL
可能会稍微偏离。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
exclude-result-prefixes="xs xd" version="2.0">
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="p">
<p>
<xsl:apply-templates/>
</p>
</xsl:template
<xsl:template match="note.ref">
<span class="noteRef" id="{@id}">
<xsl:apply-templates/>
</span>
</xsl:template>
<xsl:template match="super">
<sup>
<xsl:apply-templates/>
</sup>
</xsl:template>
<xsl:template match="note">
<div id="note-{@id}">
<xsl:apply-templates/>
</div>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:1)
这可能过于简化了,但您可以尝试匹配包含text()
的{{1}}中的p
并将其包裹起来(以及note
之后的note.ref
{1}})...
XML输入
text()
XSLT 2.0 (也可以作为1.0)
<root>
<p>
Bacon ipsum dolor sit amet bacon chuck pastrami swine pork rump, shoulder beef ribs doner tri-tip
tongue. Tri-tip ground round short ribs capicola meatloaf shank drumstick short loin pastrami t-
bone. Sirloin turducken short ribs t-bone andouille strip steak pork loin corned beef hamburger
bacon filet mignon pork chop tail.
<note.ref id="0001"><super>1</super></note.ref>
<note id="0001">
<p>
You may need to consult a latin butcher. Good Luck.
</p>
</note>
Pork loin ribeye bacon pastrami drumstick sirloin, shoulder pig jowl. Salami brisket rump ham, tail
hamburger strip steak pig ham hock short ribs jerky shank beef spare ribs. Capicola short ribs swine
beef meatball jowl pork belly. Doner leberkas short ribs, flank chuck pancetta bresaola bacon ham
hock pork hamburger fatback.
</p>
</root>
<强>输出强>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|*|processing-instruction()|comment()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/root">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="p[note]">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="p[note]/text()">
<p>
<xsl:value-of select="normalize-space(.)"/>
<xsl:apply-templates select="following-sibling::note.ref" mode="keep"/>
</p>
</xsl:template>
<xsl:template match="note">
<div id="note-{@id}">
<xsl:apply-templates/>
</div>
</xsl:template>
<xsl:template match="note.ref"/>
<xsl:template match="note.ref" mode="keep">
<span class="noteRef" id="{@id}">
<xsl:apply-templates/>
</span>
</xsl:template>
<xsl:template match="super">
<sup>
<xsl:apply-templates/>
</sup>
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select="normalize-space(.)"/>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
假设使用for-each-group
的XSLT 2.0处理器可以提供帮助:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output method="html" indent="yes" version="5.0"/>
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="p[not((.//p, .//div))]">
<xsl:copy>
<xsl:apply-templates select="@* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p[.//p, .//div]">
<xsl:for-each-group select="node()" group-adjacent="boolean((self::text(), self::note.ref))">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<p>
<xsl:apply-templates select="current()/@*, current-group()"/>
</p>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="note.ref">
<span class="noteRef" id="{@id}">
<xsl:apply-templates/>
</span>
</xsl:template>
<xsl:template match="super">
<sup>
<xsl:apply-templates/>
</sup>
</xsl:template>
<xsl:template match="note">
<div id="note-{@id}">
<xsl:apply-templates/>
</div>
</xsl:template>
</xsl:stylesheet>
模式p[not((.//p, .//div))]
和p[.//p, .//div]
以及group-adjacent
表达式boolean((self::text(), self::note.ref))
可能需要扩展,以涵盖您在输入中期望的其他类型的节点,并且需要相同的节点处理