我有一些带有<ListItem>
元素的XML,我想用<List>
元素包装任何连续的运行。因此,源XML看起来像这样:
<Section>
<Head>Heading</Head>
<Para>Blah</Para>
<ListItem>item 1</ListItem>
<ListItem>item 2</ListItem>
<ListItem>item 3</ListItem>
<ListItem>item 4</ListItem>
<Para>Something else</Para>
</Section>
我想把它转换成这样的东西:
<Section>
<Head>Heading</Head>
<Para>Blah</Para>
<List>
<ListItem>item 1</ListItem>
<ListItem>item 2</ListItem>
<ListItem>item 3</ListItem>
<ListItem>item 4</ListItem>
</List>
<Para>Something else</Para>
</Section>
使用XSLT。我确信这很明显,但我不能在晚上的这个时候解决这个问题。谢谢!
修改:大多数人都可以放心地忽略这一点。
此XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root>
<Story>
<Section id="preface">
<ChapterTitle>Redacted</ChapterTitle>
<HeadA>Redacted</HeadA>
<Body>Redacted</Body>
<BulletListItem>Item1</BulletListItem>
<BulletListItem>Item2</BulletListItem>
<BulletListItem>Item3</BulletListItem>
<BulletListItem>Item4</BulletListItem>
<HeadA>Redacted</HeadA>
<Body>Redacted</Body>
<HeadA>Redacted</HeadA>
<Body>Redacted</Body>
<Body>Redacted<Italic>REDACTED</Italic>Redacted</Body>
<BulletListItem>Second list Item1</BulletListItem>
<BulletListItem>Second list Item2</BulletListItem>
<BulletListItem>Second list Item3</BulletListItem>
<BulletListItem>Second list Item4</BulletListItem>
<Body>Redacted</Body>
</Section>
</Story>
</Root>
使用此XSL:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kFollowing" match="BulletListItem[preceding-sibling::*[1][self::BulletListItem]]"
use="generate-id(preceding-sibling::BulletListItem
[not(preceding-sibling::*[1][self::BulletListItem])])"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="BulletListItem
[not(preceding-sibling::*[1][self::BulletListItem])]">
<BulletList>
<xsl:call-template name="identity"/>
<xsl:apply-templates mode="copy" select="key('kFollowing', generate-id())"/>
</BulletList>
</xsl:template>
<xsl:template match="BulletListItem[preceding-sibling::*[1][self::BulletListItem]]"/>
<xsl:template match="BulletListItem" mode="copy">
<xsl:call-template name="identity"/>
</xsl:template>
</xsl:stylesheet>
使用Ruby REXML进行处理时,XML / XSLT会生成此XML(输出prettyprint):
<Root>
<Story>
<Section id='preface'>
<ChapterTitle>
Redacted
</ChapterTitle>
<HeadA>
Redacted
</HeadA>
<Body>
Redacted
</Body>
<BulletList>
<BulletListItem>
Item1
</BulletListItem>
<BulletListItem>
Item2
</BulletListItem>
<BulletListItem>
Item3
</BulletListItem>
<BulletListItem>
Item4
</BulletListItem>
<BulletListItem>
Second list Item2
</BulletListItem>
<BulletListItem>
Second list Item3
</BulletListItem>
<BulletListItem>
Second list Item4
</BulletListItem>
</BulletList>
<HeadA>
Redacted
</HeadA>
<Body>
Redacted
</Body>
<HeadA>
Redacted
</HeadA>
<Body>
Redacted
</Body>
<Body>
Redacted
<Italic>
REDACTED
</Italic>
Redacted
</Body>
<BulletList>
<BulletListItem>
Second list Item1
</BulletListItem>
</BulletList>
<Body>
Redacted
</Body>
</Section>
</Story>
</Root>
你会看到两个列表被卡在一起,两者之间的位丢失了。不确定这是Ruby库中还是XSLT中的错误。
答案 0 :(得分:5)
此转化:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kFollowing" match="ListItem[preceding-sibling::*[1][self::ListItem]]"
use="generate-id(preceding-sibling::ListItem
[not(preceding-sibling::*[1][self::ListItem])][1])"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ListItem
[not(preceding-sibling::*[1][self::ListItem])]">
<List>
<xsl:call-template name="identity"/>
<xsl:apply-templates mode="copy" select="key('kFollowing', generate-id())"/>
</List>
</xsl:template>
<xsl:template match="ListItem[preceding-sibling::*[1][self::ListItem]]"/>
<xsl:template match="ListItem" mode="copy">
<xsl:call-template name="identity"/>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<Section>
<Head>Heading</Head>
<Para>Blah</Para>
<ListItem>item 1</ListItem>
<ListItem>item 2</ListItem>
<ListItem>item 3</ListItem>
<ListItem>item 4</ListItem>
<Para>Something else</Para>
</Section>
产生想要的结果:
<Section>
<Head>Heading</Head>
<Para>Blah</Para>
<List>
<ListItem>item 1</ListItem>
<ListItem>item 2</ListItem>
<ListItem>item 3</ListItem>
<ListItem>item 4</ListItem>
</List>
<Para>Something else</Para>
</Section>
答案 1 :(得分:4)
此样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@*|node()[1]"/>
</xsl:copy>
<xsl:apply-templates select="following-sibling::node()[1]"/>
</xsl:template>
<xsl:template match="ListItem">
<List>
<xsl:call-template name="ListItem"/>
</List>
<xsl:apply-templates select="following-sibling::node()
[not(self::ListItem)][1]"/>
</xsl:template>
<xsl:template match="ListItem[preceding-sibling::node()[1]
/self::ListItem]"
name="ListItem">
<xsl:copy>
<xsl:apply-templates select="@*|node()[1]"/>
</xsl:copy>
<xsl:apply-templates select="following-sibling::node()[1]
/self::ListItem"/>
</xsl:template>
</xsl:stylesheet>
输出:
<Section>
<Head>Heading</Head>
<Para>Blah</Para>
<List>
<ListItem>item 1</ListItem>
<ListItem>item 2</ListItem>
<ListItem>item 3</ListItem>
<ListItem>item 4</ListItem>
</List>
<Para>Something else</Para>
</Section>
编辑3 :使用strip-space
获取内容。