注意:编辑使元素和属性值可见(之前它们是不可见的,因为我使用尖括号)并提供完整的示例XML源文件 .

我正在尝试创建XSL来执行复杂的XML到XML转换 .

我的XML有一些文本元素 <a:t> ,它们有各种路径,以 /p:sld/p:notes 开头,但总是以 /p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:t 结尾 .

这些 <a:t> 元素需要根据路径的开始方式以及(有时存在的)前一个兄弟 <a:pPr><a:r> 的属性值转换为不同的目标XML元素,而 <a:r> 又是 <a:t> 的父级 .

这是源XML的最小版本,例如:http://pastie.org/9559309

以下是各种 <a:t> 元素的xpath以及它们的目标XML . Edit: I added a new item at the start of the items whose paths start /p:notes

  • xpath /p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:t<Body>

  • xpath /p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:t<a:r> 标签前面紧跟 <a:pPr lvl="1"> )到 <Bulleted>

  • xpath /p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:t<a:r> 标签前面紧跟 <a:pPr lvl="2"> )到 <Bulleted2>

  • xpath /p:notes/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:t<Body>

  • xpath /p:notes/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:t<a:r> 标签前面有兄弟姐妹 <a:pPr lvl="1"> )到 <Body>

  • xpath /p:notes/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:t<a:r> 标签前面紧跟兄弟 <a:pPr lvl="2"> )到 <Bulleted>

  • xpath /p:notes/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:t<a:r> 标签前面有兄弟姐妹 <a:pPr lvl="3"> )到 <Bulleted2>

注意当 <a:pPr> 存在时,路径起点与 <a:pPr> 的属性值的交互是如何确定输出哪个xml元素的 . 例如:

元素 <a:t> 与父 <a:r> 紧接在 <a:pPr "lvl=1"> 之前应该生成 <Bulleted> 如果源xpath开始 /p:sld 但是如果源路径启动 /p:notes __646876_标记与其他所有相同应该是 <Body> 在输出中 .

最后,我还需要将根xpath /p:notes 附近的几个元素转换为 <PageBreak> ,将xpath /p:sld 转换为 <PageBreak> .

输出XML应如下所示 . 编辑:现在匹配源xml的内容 .

<Document>
<PageBreak></PageBreak>
<bodytext>Activity 1:</bodytext>
<bodytext>Services Platform</bodytext>
<bodytext>Objective :</bodytext>
<Bulleted>The objective of this activity is to identify which services each node supports</Bulleted>
<bodytext>Description :</bodytext>
<Bulleted>This will be an individual activity. Using the information we just covered and the drawing on the next page fill in the table with the information requested by your Instructor</Bulleted>
<bodytext>IG: Mandatory individual activity. Time: 5 – 10 min.</bodytext>
<PageBreak></PageBreak> 
<bodytext>2</bodytext>
<bodytext>Activity 1: </bodytext>
<bodytext>Services Platform</bodytext>
<bodytext>To complete this activity, use the following material:</bodytext>
<Bulleted>The drawing and table on the next page, along with the information provided by your Instructor.</Bulleted>
</Document>

<PageBreak> 是一个空元素, <bodytext><Bullet> 元素包含源XML中相关 <a:t> 的文本,源XML中的所有其他元素都被剥离 .

更新:我已经编写了一些xsl,它似乎应该能够在输入xml中获取每个a:t元素的内容,并在输出上放置相应的输出元素名称 . 身体被改为bodytext,这样我就不会出现身体成为保留html词的问题 .

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">
<xsl:template match="/">
    <xsl:for-each select="//a:t/">
        <xsl:choose>
            <xsl:when test="(count(ancestor::p:sld) > 0) and (count(ancestor::a:r[preceding-sibling[1]@lvl='1']) > 0">
                <bulleted><xsl:value-of select="."/></bulleted>
            </xsl:when>
            <xsl:when test="(count(ancestor::p:sld) > 0) and (count(ancestor::a:r[preceding-sibling[1]@lvl='2']) > 0">
                <bulleted2><xsl:value-of select="."/></bulleted2>
            </xsl:when>         
            <xsl:when test="(count(ancestor::p:notes) > 0) and (count(ancestor::a:r[preceding-sibling[1]@lvl='2']) > 0">
                <bulleted><xsl:value-of select="."/></bulleted>
            </xsl:when>
            <xsl:when test="(count(ancestor::p:notes) > 0) and (count(ancestor::a:r[preceding-sibling[1]@lvl='3']) > 0">
                <bulleted><xsl:value-of select="."/></bulleted>
            </xsl:when>
    <xsl:otherwise>
                <bodytext><xsl:value-of select="."/></bodytext>
    </xsl:otherwise>
</xsl:choose>
</xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

我从Transform获得的语法错误与 a:t 使用前缀我不确定如何修复这些错误这一事实有关 .

我也不确定如何告诉Transform XSL处理器在输出上放置分页符,其中每个p.sld或p.notes元素出现在输入上并让它们显示在适当的位置 . 好像我应该做一个外部的“for-each /document/p.sld或/document/p.notes”命令

  • 输出 <pagebreak></pagebreak> 标记对

  • 然后在上面的代码中启动另一个内部for-each a:t ,但仅限于当前由外部选择的 p.sldp.notes 元素的范围

  • 然后关闭外部for-each命令,发送处理器以查找源xml中的下一个 p.sldp.notes .

感谢您的任何帮助,您可以提供 .