ODT XML 文件的 XSL 更改结构
XSL change structure of ODT XML file
我正在尝试使用 XSLT 将 fodt 文件转换为不同的结构。
我有以下 xml(从 fodt 文件中提取)
<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>
它由章节层次结构(text:h)组成,里面是文本或列表或图像(text:p,text:list或draw:frame)。
我想做的是:
- 将每一章放入一个块“Titre”中;
- 与其将章节作为兄弟姐妹,不如将它们作为父子;
- 将 office 标签转换为 html 个。
我设法使用 XSLT: Select following-sibling until reaching a specified tag 的答案完成了第一部分。
-编辑-
感谢 Bryn 的帮助,我现在可以将 FODT 标签转换为 HTML.
所以现在,我需要做的就是将每个章节块放在一起,但我不知道该怎么做。
这是我的 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>
这是我目前的结果:
<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>
这是预期的结果:
<?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>
谢谢
感谢来自此线程 的 Bryn 和 Martin Honnen,这是一个可行的解决方案:
<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>
我正在尝试使用 XSLT 将 fodt 文件转换为不同的结构。
我有以下 xml(从 fodt 文件中提取)
<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>
它由章节层次结构(text:h)组成,里面是文本或列表或图像(text:p,text:list或draw:frame)。
我想做的是:
- 将每一章放入一个块“Titre”中;
- 与其将章节作为兄弟姐妹,不如将它们作为父子;
- 将 office 标签转换为 html 个。
我设法使用 XSLT: Select following-sibling until reaching a specified tag 的答案完成了第一部分。
-编辑- 感谢 Bryn 的帮助,我现在可以将 FODT 标签转换为 HTML.
所以现在,我需要做的就是将每个章节块放在一起,但我不知道该怎么做。
这是我的 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>
这是我目前的结果:
<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>
这是预期的结果:
<?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>
谢谢
感谢来自此线程
<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>