Tôi có một số XML với các yếu tố <ListItem>
và tôi muốn bao gồm bất kỳ lần chạy liên tiếp nào với các yếu tố <List>
. Vì vậy, nguồn XML sẽ giống như thế này:Làm cách nào để bọc một nhóm các phần tử liền kề bằng XSLT?
<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>
Và tôi muốn chuyển nó sang một cái gì đó như thế này:
<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>
sử dụng XSLT. Tôi chắc chắn nó là hiển nhiên nhưng tôi không thể làm việc nó ra vào lúc này vào buổi tối. Cảm ơn!
Edit: này có thể được bỏ qua một cách an toàn bởi hầu hết mọi người.
XML này:
<?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>
Với XSL này:
<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>
Khi xử lý với Ruby REXML và XML/XSLT tạo ra XML này (đầu ra 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>
Bạn sẽ thấy rằng hai danh sách bị kẹt lại với nhau và bit ở giữa bị mất. Không chắc chắn nếu đây là một lỗi trong thư viện Ruby hoặc trong XSLT của bạn.
Tôi quá lai cho tìm kiếm trùng lặp ... Nếu ai đó đăng các liên kết tôi sẽ xóa câu trả lời. –
Câu hỏi hay, +1. Xem câu trả lời của tôi cho một giải pháp dựa trên khóa hiệu quả. –
Tôi lấy lại những gì tôi nói về nó là hiển nhiên: P Tôi thực sự cần phải học XSLT đúng cách ... – Skilldrick