XML到XML转换基于先前兄弟的祖先和祖先的属性值

时间:2014-09-09 17:05:56

标签: xml xslt xpath

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

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

我的XML有一些文本元素<a:t>,它们有各种路径 从/p:sld/p:notes开始,但始终以。{1}}开头 /p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:t

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

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

以下是各种<a:t>元素的xpath以及它们的目标XML。 修改:我在路径开始为/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元素。例如:

如果源xpath开始<a:t>,那么<a:r>父元素<a:pPr "lvl=1">前面紧跟<Bulleted>的元素应生成/p:sld 但是,如果源路径启动/p:notes,则<a:t>标记中包含其他所有内容的标记应该在输出中为<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>标记对
  • 然后在上面的代码中为每个a:t启动另一个内部,但仅限于当前由外部为每个选择的p.sldp.notes元素的范围
  • 然后关闭外部for-each命令,发送处理器以查找源xml中的下一个p.sldp.notes

感谢您提供的任何帮助。

0 个答案:

没有答案