ODT XML 文件的 XSL 更改结构 [英] XSL change structure of ODT XML file

查看:31
本文介绍了ODT XML 文件的 XSL 更改结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 XSLT 将 fodt 文件转换为不同的结构.

我有以下 xml(从 fodt 文件中提取)

</text:h><text:p>第 1 段</text:p><text:p>第2段</text:p><text:h text:outline-level=1">2.章节</text:h><text:p>第 1 段</text:p><text:h text:outline-level=2"><text:soft-page-break/>2.1.章节<text:h text:outline-level=3">2.1.1.章节<text:p>列表:</text:p><文本:列表><文本:列表项><text:p>项目 1</text:p></text:list-item><文本:列表项><text:p>项目 2</text:p></text:list-item><文本:列表项><text:p>项目 3</text:p></text:list-item></text:list><text:h text:outline-level=3">2.1.2.章节<text:p>第 1 段</text:p><text:h text:outline-level=2"><文本:书签/>2.2.章节</text:h><text:p>第 1 段</text:p><文本:p><draw:frame draw:name="Image1"><绘制:图像><office:binary-data>53dgh5436dfgh54</office:binary-data></draw:image></draw:frame></text:p><text:h text:outline-level=1">3.章节</text:h><text:p>第 1 段</text:p><text:p>第2段</text:p><text:p>第3段</text:p></office:text></office:body></office:document>

它由章节层次结构(text:h)组成,内部是文本或列表或图像(text:p、text:list 或 draw:frame).

我想做的是:

  • 将每一章放入一个标题"块中;;
  • 与其将章节作为兄弟姐妹,不如让它们成为父子;
  • 将 office 标签转换为 html 标签.

我设法使用 XSLT:选择跟随兄弟直到到达指定的标签.

-编辑-感谢 Bryn 的帮助,我现在可以将 FODT 标签转换为 HTML.

所以现在,我所需要的就是把每一章都放在一起,我不知道该怎么做.

这是我的 XSL :

 <xsl:output method="xml"缩进=是"/><xsl:strip-space elements="*"/><!-- 我的第一个节点--><xsl:template match="/"><plus:ReglementDU><xsl:apply-templates/></plu:ReglementDU></xsl:模板><!-- 删除 officeblabla --><xsl:template match="*[following::text:h[1] and not(self::text:h[1])]"/><!-- 插入标题块--><xsl:template match="text:h"><xsl:variable name="header-id";select="generate-id(.)"/><加:标题><h1><xsl:apply-templates/><xsl:for-each select="following::*[generate-id(preceding-sibling::text:h[1]) = $header-id]"><xsl:call-template name="convertHTML"><xsl:with-param name="content";选择=."/></xsl:call-template></xsl:for-each></plu:Titre></xsl:模板><!-- 删除复制的内容--><xsl:template match="text:p"/><!-- 将内容转换为 HTML --><xsl:template name="convertHTML"><xsl:param name="content"/><xsl:for-each select="$content"><xsl:if test="name(.)='text:p'and name(./*[1])!='draw:frame'"><div><xsl:value-of select="."/>

</xsl:if><xsl:if test="name(.)='text:list'"><ul><xsl:for-each select="./*"><li><xsl:value-of select="."/></xsl:for-each></xsl:if><xsl:if test="name(./*)='draw:frame'"><a><xsl:value-of select="./draw:frame/@draw:name"/></a></xsl:if></xsl:for-each></xsl:模板></xsl:stylesheet>

这是我目前的结果:

<加:标题><h1>1.滴度/h1<div>第1段</div><div>第2段</div></plu:Titre><加:标题><h1>2.滴度/h1<div>第1段</div></plu:Titre><加:标题><h1>2.1.滴度/h1</plu:Titre><加:标题><h1>2.1.1.滴度/h1<div>列表:</div><ul><li>项目 1</li><li>项目 2</li><li>项目 3</li></plu:Titre><加:标题><h1>2.1.2.滴度/h1<div>第1段</div></plu:Titre><加:标题><h1>2.2.滴度/h1<div>第1段</div><a>图像1</a></plu:Titre><加:标题><h1>3.滴度/h1<div>第1段</div><div>第2段</div><div>第3段</div></plu:Titre></plu:ReglementDU>

这是预期的结果:

<plu:ReglementDU xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0";xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0";xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0";xmlns:plu=https://cnig.gouv.fr/reglementDU"><加:标题><h1>1.滴度/h1<div>第1段</div><div>第2段</div></plu:Titre><加:标题><h1>2.滴度/h1<div>第1段</div><加:标题><h1>2.1.滴度/h1<加:标题><h1>2.1.1.滴度/h1<div>列表:</div><ul><li>项目 1</li><li>项目 2</li><li>项目 3</li></plu:Titre><加:标题><h1>2.1.2.滴度/h1<div>第1段</div></plu:Titre></plu:Titre><加:标题><h1>2.2.滴度/h1<div>第1段</div><a>图像1</a></plu:Titre></plu:Titre><加:标题><h1>3.滴度/h1<div>第1段</div><div>第2段</div><div>第3段</div></plu:Titre></plu:ReglementDU>

谢谢

解决方案

感谢此主题中的 Bryn 和 Martin Honnen 如何将平面xml数据转换为分层数据xml 2,这是一个可行的解决方案:

<!-- supprime les blancs--><xsl:strip-space elements="*"/><!-- 缩进 XML 结果--><xsl:output indent="yes"/><!--==================== 模板 ======================--><!-- 抑制 des balises 办公室--><xsl:template match="*[following::text:h[1] and not(self::text:h[1])]"/><xsl:template match="text:*[not(text:p or text:h or text:list or text:list-item)]"/><!-- 模板fourre-tout --><xsl:template match="node()|@*"><xsl:apply-templates/></xsl:模板><!-- 模板主体--><xsl:template match="office:text|@*"><plus:ReglementDU><xsl:sequence select="mf:group(*, 1)"/></plu:ReglementDU></xsl:模板><!-- 转换 ODT/html --><xsl:template name="convertHTML"><xsl:param name="content"/><xsl:for-each select="$content"><xsl:if test="name(.)='text:p'and name(./*[1])!='draw:frame'"><div><xsl:value-of select="."/>

</xsl:if><xsl:if test="name(.)='text:list'"><ul><xsl:for-each select="./*"><li><xsl:value-of select="."/></xsl:for-each></xsl:if><xsl:if test="name(./*[1])='draw:frame'"><a><xsl:value-of select="./draw:frame/@draw:name"/></a></xsl:if></xsl:for-each></xsl:模板><!-- ====================== 函数 ======================== --><!-- fonction pemettant de hiérarchiser les titres --><xsl:function name="mf:group";as=元素()*"><xsl:param name="elements";as=element()*"/><xsl:param name="level";as=xs:整数"/><xsl:for-each-group select="$elements";group-starting-with=text:h[@text:outline-level = $level]"><xsl:when test="not(self::text:h[@text:outline-level = $level])"><xsl:where-populated><xsl:call-template name="convertHTML"><xsl:with-param name="content";选择=当前组()"/></xsl:call-template></xsl:where-populated></xsl:when><xsl:否则><plu:Titre niveau={$level}"><xsl:element name="{concat('h',$level)}"><xsl:value-of select="."/></xsl:element><xsl:sequence select="mf:group(current-group() except ., ($level + 1))"/></plu:Titre></xsl:否则></xsl:选择></xsl:for-each-group></xsl:function></xsl:stylesheet>

I am trying to convert an fodt file into a different structure using XSLT.

I have the following xml (extracted from an fodt file)

<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"> 
    <office:blablaTags>
        officeblabla
    </office:blablaTags>

    <office:body>
        <office:text text:use-soft-page-breaks="true">
            <text:variable-decls>
officeBlabla
            </text:variable-decls>
            <text:h text:outline-level="1">1. Chapter<text:variable-set/>
            </text:h>
            <text:p>paragraphe 1</text:p>
            <text:p>paragraphe 2</text:p>
            <text:h text:outline-level="1">2. Chapter<text:variable-set/>
            </text:h>
            <text:p>paragraphe 1</text:p>
            <text:h text:outline-level="2">
                <text:soft-page-break/>2.1. Chapter</text:h>
            <text:h text:outline-level="3">2.1.1. Chapter</text:h>
            <text:p>liste :</text:p>
            <text:list>
                <text:list-item>
                    <text:p>item 1</text:p>
                </text:list-item>
                <text:list-item>
                    <text:p>item 2</text:p>
                </text:list-item>
                <text:list-item>
                    <text:p>item 3</text:p>
                </text:list-item>
            </text:list>
            <text:h text:outline-level="3">2.1.2. Chapter</text:h>
            <text:p>paragraphe 1</text:p>
            <text:h text:outline-level="2">
                <text:bookmark/>2.2. Chapter<text:variable-set/>
            </text:h>
            <text:p>paragraphe 1</text:p>
            <text:p>
                <draw:frame draw:name="Image1">
                    <draw:image>
                        <office:binary-data>53dgh5436dfgh54
      </office:binary-data>
                    </draw:image>
                </draw:frame>
            </text:p>
            <text:h text:outline-level="1">3. Chapter<text:variable-set/>
            </text:h>
            <text:p>Paragraphe 1</text:p>
            <text:p>Paragraphe 2</text:p>
            <text:p>Paragraphe 3</text:p>
        </office:text>
    </office:body>
</office:document>

It is composed of a hierarchy of chapters (text:h) and inside are text or lists or images (text:p, text:list or draw:frame).

And what I would like to do is :

  • Put each chapter into a bloc "Titre" ;
  • Instead of having chapters as siblings, having them as parent-child ;
  • Convert office tags to html ones.

I managed to do the first part using the answer from XSLT: Select following-sibling until reaching a specified tag.

-EDIT- Thanks to the help of Bryn, i am now able to convert FODT tags into HTML.

So now, all i need is to put every chapter bloc into each other and I have no idea how to do this.

So here is my XSL :

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:plu="https://cnig.gouv.fr/reglementDU">
    <xsl:output method="xml" indent="yes"/>
    <xsl:strip-space elements="*"/>
    <!-- my first node -->
    <xsl:template match="/">
        <plu:ReglementDU>
            <xsl:apply-templates/>
        </plu:ReglementDU>
    </xsl:template>
    <!-- delete officeblabla -->
    <xsl:template match="*[following::text:h[1] and not(self::text:h[1])]"/>
    <!-- insert Titre blocs -->
    <xsl:template match="text:h">
        <xsl:variable name="header-id" select="generate-id(.)"/>
        <plu:Titre>
            <h1>
                <xsl:apply-templates/>
            </h1>
            <xsl:for-each select="following::*[generate-id(preceding-sibling::text:h[1]) = $header-id]">
                <xsl:call-template name="convertHTML">
                    <xsl:with-param name="content" select="."/>
                </xsl:call-template>
            </xsl:for-each>
        </plu:Titre>
    </xsl:template>
    <!-- delete copied content -->
    <xsl:template match="text:p"/>
    <!-- convert content to HTML -->
    <xsl:template name="convertHTML">
        <xsl:param name="content"/>
        <xsl:for-each select="$content">
            <xsl:if test="name(.)='text:p'and name(./*[1])!='draw:frame'">
                <div>
                    <xsl:value-of select="."/>
                </div>
            </xsl:if>
            <xsl:if test="name(.)='text:list'">
                <ul>
                    <xsl:for-each select="./*">
                        <li>
                            <xsl:value-of select="."/>
                        </li>
                    </xsl:for-each>
                </ul>
            </xsl:if>
            <xsl:if test="name(./*)='draw:frame'">
                <a>
                    <xsl:value-of select="./draw:frame/@draw:name"/>
                </a>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Here is my current result :

<plu:ReglementDU xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:plu="https://cnig.gouv.fr/reglementDU">
    <plu:Titre>
        <h1>1. Titre</h1>
        <div>paragraphe 1</div>
        <div>paragraphe 2</div>
    </plu:Titre>
    <plu:Titre>
        <h1>2. Titre</h1>
        <div>paragraphe 1</div>
    </plu:Titre>
    <plu:Titre>
        <h1>2.1. Titre</h1>
    </plu:Titre>
    <plu:Titre>
        <h1>2.1.1. Titre</h1>
        <div>liste :</div>
        <ul>
            <li>item 1</li>
            <li>item 2</li>
            <li>item 3</li>
        </ul>
    </plu:Titre>
    <plu:Titre>
        <h1>2.1.2. Titre</h1>
        <div>paragraphe 1</div>
    </plu:Titre>
    <plu:Titre>
        <h1>2.2. Titre</h1>
        <div>paragraphe 1</div>
        <a>Image1</a>
    </plu:Titre>
    <plu:Titre>
        <h1>3. Titre</h1>
        <div>Paragraphe 1</div>
        <div>Paragraphe 2</div>
        <div>Paragraphe 3</div>
    </plu:Titre>
</plu:ReglementDU>

Here is the expected result :

<?xml version="1.0" encoding="UTF-8"?>
<plu:ReglementDU xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:plu="https://cnig.gouv.fr/reglementDU">
    <plu:Titre>
        <h1>1. Titre</h1>
        <div>paragraphe 1</div>
        <div>paragraphe 2</div>
    </plu:Titre>
    <plu:Titre>
        <h1>2. Titre</h1>
        <div>paragraphe 1</div>
        <plu:Titre>
            <h1>2.1. Titre</h1>
            <plu:Titre>
                <h1>2.1.1. Titre</h1>
                <div>liste :</div>
                <ul>
                    <li>item 1</li>
                    <li>item 2</li>
                    <li>item 3</li>
                </ul>
            </plu:Titre>
            <plu:Titre>
                <h1>2.1.2. Titre</h1>
                <div>paragraphe 1</div>
            </plu:Titre>
        </plu:Titre>
        <plu:Titre>
            <h1>2.2. Titre</h1>
            <div>paragraphe 1</div>
            <a>Image1</a>
        </plu:Titre>
    </plu:Titre>
    <plu:Titre>
        <h1>3. Titre</h1>
        <div>Paragraphe 1</div>
        <div>Paragraphe 2</div>
        <div>Paragraphe 3</div>
    </plu:Titre>
</plu:ReglementDU>

Thanks

解决方案

Thanks to Bryn and Martin Honnen from this thread How to convert flat xml data to hierarchical data xml 2, here is a working solution :

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mf="http://example.com/mf" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:plu="https://cnig.gouv.fr/reglementDU" version="3.0" exclude-result-prefixes="mf office text draw">
    <!-- supprime les blancs-->
    <xsl:strip-space elements="*"/>
    <!-- indente le XML résultat-->
    <xsl:output indent="yes"/>
    <!--===================== Templates =====================-->
    <!-- suppression des balises office -->
    <xsl:template match="*[following::text:h[1] and not(self::text:h[1])]"/>
    <xsl:template match="text:*[not(text:p or text:h or text:list or text:list-item)]"/>
    <!-- template fourre-tout -->
    <xsl:template match="node()|@*">
        <xsl:apply-templates/>
    </xsl:template>
    <!-- template principal -->
    <xsl:template match="office:text|@*">
        <plu:ReglementDU>
            <xsl:sequence select="mf:group(*, 1)"/>
        </plu:ReglementDU>
    </xsl:template>
    <!-- conversion ODT/html -->
    <xsl:template name="convertHTML">
        <xsl:param name="content"/>
        <xsl:for-each select="$content">
            <xsl:if test="name(.)='text:p'and name(./*[1])!='draw:frame'">
                <div>
                    <xsl:value-of select="."/>
                </div>
            </xsl:if>
            <xsl:if test="name(.)='text:list'">
                <ul>
                    <xsl:for-each select="./*">
                        <li>
                            <xsl:value-of select="."/>
                        </li>
                    </xsl:for-each>
                </ul>
            </xsl:if>
            <xsl:if test="name(./*[1])='draw:frame'">
                <a>
                    <xsl:value-of select="./draw:frame/@draw:name"/>
                </a>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
    <!-- ====================== functions ======================== -->
    <!-- fonction pemettant de hiérarchiser les titres -->
    <xsl:function name="mf:group" as="element()*">
        <xsl:param name="elements" as="element()*"/>
        <xsl:param name="level" as="xs:integer"/>
        <xsl:for-each-group select="$elements" group-starting-with="text:h[@text:outline-level = $level]">
            <xsl:choose>
                <xsl:when test="not(self::text:h[@text:outline-level = $level])">
                    <xsl:where-populated>
                        <xsl:call-template name="convertHTML">
                            <xsl:with-param name="content" select="current-group()"/>
                        </xsl:call-template>
                    </xsl:where-populated>
                </xsl:when>
                <xsl:otherwise>
                    <plu:Titre niveau="{$level}">
                        <xsl:element name="{concat('h',$level)}">
                            <xsl:value-of select="."/>
                        </xsl:element>
                        <xsl:sequence select="mf:group(current-group() except ., ($level + 1))"/>
                    </plu:Titre>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </xsl:function>
</xsl:stylesheet>

这篇关于ODT XML 文件的 XSL 更改结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆