How to add an element to an existing xml file at specific locations using python? - python-docx

part of word document xml:
<w:p w14:paraId="1A403538" w14:textId="03591853" w:rsidR="00280630" w:rsidRDefault="00280630" w:rsidP="00280630">
<w:pPr>
<w:pStyle w:val="Heading1"/>
<w:rPr>
<w:lang w:val="en-US"/>
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:lang w:val="en-US"/>
</w:rPr>
<w:lastRenderedPageBreak/>
<w:t>Chapter to Hide</w:t>
</w:r>
</w:p>
I would like to add a <w:vanish/> element programmatically where it is seen below:
<w:p w14:paraId="1A403538" w14:textId="03591853" w:rsidR="00280630" w:rsidRPr="000E4C6C" w:rsidRDefault="00280630" w:rsidP="00280630">
<w:pPr>
<w:pStyle w:val="Heading1"/>
<w:rPr>
<w:vanish/>
<w:lang w:val="en-US"/>
</w:rPr>
</w:pPr>
<w:r w:rsidRPr="000E4C6C">
<w:rPr>
<w:vanish/>
<w:lang w:val="en-US"/>
</w:rPr>
<w:lastRenderedPageBreak/>
<w:t>Chapter to Hide</w:t>
</w:r>
</w:p>
What I want to do would be something like this:
from docx import Document
doc = Document("invitation.docx")
for paragraph in doc.paragraphs:
p = paragraph._element
if '''(paraId == "1A403538")''':
run_pr = p.xpath('./w:pPr/w:rPr')
# append <vanish/>
Something I tried:
import xml.etree.ElementTree as ET
from xml.dom import minidom
trees = minidom.parse("document.xml")
tagnames = trees.getElementsByTagName("w:rPr")
for tag in tagnames:
child = ET.fromstring("<vanish/>")
tag.appendChild(child)
I get the following error from line tag.appendChild(child):
AttributeError: 'xml.etree.ElementTree.Element' object has no attribute 'nodeType'

Related

XSLT conversion of open XML into clean HTML lists

I have created an XSLT file that converts everything in a Word XML into clean HTML however I am unable to covert nested lists properly.
I saved a word v16.12 file into XML. The Word file contains two lists
Here is the exported Open XML (relating to just the bullets).
<w:body>
<w:p w:rsidR="00875AF6" w:rsidRDefault="007A38EC" w:rsidP="007A38EC">
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t>List 1 Bullet 1 level 1</w:t>
</w:r>
</w:p>
<w:p w:rsidR="007A38EC" w:rsidRDefault="007A38EC" w:rsidP="007A38EC">
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t>List 1 Bullet 2 level 1</w:t>
</w:r>
</w:p>
<w:p w:rsidR="007A38EC" w:rsidRDefault="007A38EC" w:rsidP="007A38EC">
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="1"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t>List 1 Bullet 3 level 2</w:t>
</w:r>
</w:p>
<w:p w:rsidR="007A38EC" w:rsidRDefault="007A38EC" w:rsidP="007A38EC">
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="2"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t>List 1 Bullet 4 level 3</w:t>
</w:r>
</w:p>
<w:p w:rsidR="007A38EC" w:rsidRDefault="007A38EC" w:rsidP="007A38EC">
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="2"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t>List 1 Bullet 5 level 3</w:t>
</w:r>
</w:p>
<w:p w:rsidR="007A38EC" w:rsidRDefault="007A38EC" w:rsidP="007A38EC">
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="1"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t>List 1 Bullet 6 level 2</w:t>
</w:r>
</w:p>
<w:p w:rsidR="007A38EC" w:rsidRDefault="007A38EC" w:rsidP="007A38EC">
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="2"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t>List 1 Bullet 7 level 3</w:t>
</w:r>
</w:p>
<w:p w:rsidR="007A38EC" w:rsidRDefault="007A38EC" w:rsidP="007A38EC">
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t>List 1 Bullet 8 level 1</w:t>
</w:r>
</w:p>
<w:p w:rsidR="007A38EC" w:rsidRDefault="007A38EC" w:rsidP="00575241"/>
<w:p w:rsidR="00575241" w:rsidRDefault="00575241" w:rsidP="00575241">
<w:r>
<w:t>This is a break</w:t>
</w:r>
</w:p>
<w:p w:rsidR="00575241" w:rsidRDefault="00575241" w:rsidP="00575241"/>
<w:p w:rsidR="007A38EC" w:rsidRDefault="007A38EC" w:rsidP="00575241">
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="2"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t>List 2 Bullet 1 level 1</w:t>
</w:r>
</w:p>
<w:p w:rsidR="007A38EC" w:rsidRDefault="007A38EC" w:rsidP="00575241">
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="1"/>
<w:numId w:val="2"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t>List 2 Bullet 2 level 2</w:t>
</w:r>
</w:p>
<w:p w:rsidR="007A38EC" w:rsidRDefault="007A38EC" w:rsidP="00575241">
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="2"/>
<w:numId w:val="2"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t>List 2 Bullet 3 level 3</w:t>
</w:r>
</w:p>
<w:p w:rsidR="007A38EC" w:rsidRDefault="007A38EC" w:rsidP="00575241">
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="2"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t>List 2 Bullet 4 level 1</w:t>
</w:r>
</w:p>
<w:p w:rsidR="007A38EC" w:rsidRDefault="007A38EC" w:rsidP="00575241">
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="1"/>
<w:numId w:val="2"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t>List 2 Bullet 5 level 2</w:t>
</w:r>
</w:p>
<w:p w:rsidR="007A38EC" w:rsidRDefault="007A38EC" w:rsidP="00575241">
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="1"/>
<w:numId w:val="2"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t>List 2 Bullet 6 level 2</w:t>
</w:r>
</w:p>
<w:p w:rsidR="007A38EC" w:rsidRDefault="007A38EC" w:rsidP="00575241">
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="2"/>
<w:numId w:val="2"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t>List 2 Bullet 7 level 3</w:t>
</w:r>
<w:bookmarkStart w:id="0" w:name="_GoBack"/>
<w:bookmarkEnd w:id="0"/>
</w:p>
<w:p w:rsidR="007A38EC" w:rsidRDefault="007A38EC" w:rsidP="00575241">
<w:pPr>
<w:pStyle w:val="ListParagraph"/>
<w:numPr>
<w:ilvl w:val="1"/>
<w:numId w:val="2"/>
</w:numPr>
</w:pPr>
<w:r>
<w:t>List 2 Bullet 8 level 2</w:t>
</w:r>
</w:p>
<w:p w:rsidR="007A38EC" w:rsidRDefault="007A38EC" w:rsidP="00575241"/>
<w:sectPr w:rsidR="007A38EC" w:rsidSect="00D678D3">
<w:pgSz w:w="11900" w:h="16840"/>
<w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440"
w:header="708" w:footer="708" w:gutter="0"/>
<w:cols w:space="708"/>
<w:docGrid w:linePitch="360"/>
</w:sectPr>
</w:body>
Using XSLT I need to convert the XML into this HTML
<ul>
<li>List 1 Bullet 1 level 1</li>
<li>List 1 Bullet 2 level 1
<ul>
<li>List 1 Bullet 3 level 2
<ul>
<li>List 1 Bullet 4 level 3</li>
<li>List 1 Bullet 5 level 3</li>
</ul>
</li>
<li>List 1 Bullet 6 level 2
<ul>
<li>List 1 Bullet 7 level 3</li>
</ul>
</li>
</ul>
</li>
<li>List 1 Bullet 8 level 1</li>
</ul>
<p>This is a gap</p>
<ul>
<li>List 2 Bullet 1 level 1
<ul>
<li>List 2 Bullet 2 level 2
<ul>
<li>List 2 Bullet 3 level 3</li>
</ul>
</li>
</ul>
</li>
<li>List 2 Bullet 4 level 1
<ul>
<li>List 2 Bullet 5 level 2</li>
<li>List 2 Bullet 6 level 2
<ul>
<li>List 2 Bullet 7 level 3</li>
</ul>
</li>
<li>List 2 Bullet 8 level 2</li>
</ul>
</li>
</ul>
I have researched and the closest I found to was using a function and for-each-group like the below.
<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" version="2.0"
exclude-result-prefixes="xs mf">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:function name="mf:group" as="node()*">
<xsl:param name="nodes" as="node()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:if test="$nodes">
<list type="ul">
<xsl:for-each-group select="$nodes"
group-adjacent="boolean(self::*[#level = $level])">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:apply-templates select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="mf:group(current-group(), $level + 1)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</list>
</xsl:if>
</xsl:function>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#*, node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item[#level]">
<item>
<xsl:apply-templates/>
</item>
</xsl:template>
<xsl:template match="test">
<xsl:copy>
<xsl:for-each-group select="*" group-adjacent="boolean(self::item)">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:sequence select="mf:group(current-group(), 0)"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Unfortunately using functions and the for-each-group is beyond my ability. My question is how would I amend the above XSLT to work with the XML that I am getting from Word?
First off, we'll start with an identity template:
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#*, node()"/>
</xsl:copy>
</xsl:template>
Second, we have to match the root node w:body and group the elements using xsl:for-each-group. Afterwards, we'll store the nodes in a variable (firstpass) to further manipulate the nodes later, such as:
<!-- If you want to specify the target node (1 in 22 as you say),
you can adjust the xpath below to match your target node.
-->
<xsl:template match="w:body">
<xsl:variable name="firstPass">
<xsl:for-each-group select="*" group-adjacent="boolean(self::w:p[descendant::w:ilvl])">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<!-- the zero (0) was obtained from the value of
w:val attribute of w:ilvl node -->
<xsl:sequence select="mf:group(current-group(), 0)"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:variable>
<xsl:apply-templates select="$firstPass/node()"/>
</xsl:template>
we can adapt the function that you mentioned. We can modify the group-adjacent target nodes to
<xsl:function name="mf:group" as="node()*">
<xsl:param name="nodes" as="node()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:if test="$nodes">
<ul>
<xsl:for-each-group select="$nodes"
group-adjacent="boolean(self::*[descendant::w:ilvl/#w:val = $level])">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:apply-templates select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="mf:group(current-group(), $level + 1)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</ul>
</xsl:if>
</xsl:function>
The following are the templates needed for the cleanup
<xsl:template match="w:p">
<xsl:apply-templates select="descendant::w:t"/>
</xsl:template>
<xsl:template match="w:p[.='']|w:sectPr"/>
<xsl:template match="w:t">
<xsl:choose>
<xsl:when test="ancestor::w:p[descendant::w:pStyle[#w:val='ListParagraph']]">
<li>
<xsl:apply-templates/>
</li>
</xsl:when>
<xsl:otherwise>
<p>
<xsl:apply-templates/>
</p>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
After that, we still need to insert the <ul> sublevels into parent <li>. To do that, we have to do a second pass of transformation.
We will now then match the nodes present in the firstpass variable
<xsl:template match="li[following-sibling::*[1][name()='ul']]">
<xsl:copy>
<xsl:apply-templates/>
<!-- this will copy the target ul nodes, albeit in a different mode -->
<xsl:apply-templates select="following-sibling::*[1][name()='ul']" mode="transfer"/>
</xsl:copy>
</xsl:template>
<!-- this will delete the target node -->
<xsl:template match="ul[preceding-sibling::*[1][name()='li']]"/>
and an identity template for the other mode
<xsl:template match="#* | node()" mode="transfer">
<xsl:copy>
<xsl:apply-templates select="#*, node()"/>
</xsl:copy>
</xsl:template>
The whole stylesheet is as follows:
<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:w="www.wnamespace.com"
version="2.0"
exclude-result-prefixes="xs mf w">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes" omit-xml-declaration="yes"/>
<xsl:function name="mf:group" as="node()*">
<xsl:param name="nodes" as="node()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:if test="$nodes">
<ul>
<xsl:for-each-group select="$nodes"
group-adjacent="boolean(self::*[descendant::w:ilvl/#w:val = $level])">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:apply-templates select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="mf:group(current-group(), $level + 1)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</ul>
</xsl:if>
</xsl:function>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#*, node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="#* | node()" mode="transfer">
<xsl:copy>
<xsl:apply-templates select="#*, node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="w:p">
<xsl:apply-templates select="descendant::w:t"/>
</xsl:template>
<xsl:template match="w:p[.='']|w:sectPr"/>
<xsl:template match="w:t">
<xsl:choose>
<xsl:when test="ancestor::w:p[descendant::w:pStyle[#w:val='ListParagraph']]">
<li>
<xsl:apply-templates/>
</li>
</xsl:when>
<xsl:otherwise>
<p>
<xsl:apply-templates/>
</p>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="w:body">
<xsl:variable name="firstPass">
<xsl:for-each-group select="*" group-adjacent="boolean(self::w:p[descendant::w:ilvl])">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:sequence select="mf:group(current-group(), 0)"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:variable>
<xsl:apply-templates select="$firstPass/node()"/>
</xsl:template>
<xsl:template match="ul[preceding-sibling::*[1][name()='li']]"/>
</xsl:stylesheet>
See it in action here.

for element in ant build.xml

I am using a build.xml(ant) and code looks as follows,
<junit fork="yes" dir="." >
----------
---------
<for list="1,2,3,4,5,6" param="Val">
<env key="environment" value="${Val}" />
<batchtest fork="yes" todir="${junitreport.todir}">
<fileset dir="src/java">
<include name="TestOne.java" />
<include name="TestTwo.java" />
</fileset>
</batchtest>
</for>
</junit>
while running this i get the following error,
junit doesn't support the nested "for" element.
Is there any other way to achieve this loop in junit?
Please help.
Swap the <for> and the <junit> elements so <for> is on the outside and <junit> is on the inside:
<for list="1,2,3,4,5,6" param="Val" delimiter=",">
<sequential>
<junit ...>
<!-- Use an at-sign to reference the "param" from "for". -->
<env key="environment" value="#{Val}" />
</junit>
</sequential>
</for>
Note, that Val is referenced as #{Val} with an at-sign (#), not a dollar sign ($).

Set Header and Footer in a Documnet

I have a problem. I need to set following in a Document which is written on WordML.
Set Header and Footer in the document
Set an Image in the document
Set a Heading and center it
So far I have tried out these.
<w:p>
<w:pPr>
<w:jc w:val="center"/>
<w:b w:val="on"/>
</w:pPr>
<w:r>
<w:t>ABC COMPANY PRIVATE LIMITED</w:t>
</w:r>
<w:br/>
<w:r>
<w:u w:val="single"/>
<w:t>QUOTA APPLICATION FORM</w:t>
</w:r>
</w:p>
Thanks In Advance.
Set an Image to a Document (WordML)
<w:pict>
<w:binData w:name="wordml://02000001.jpg">/9j/4AA..Xof/9k=</w:binData>
<v:shape id="_x0000_i1025" style="width:100%;height:auto" type="#_x0000_t75">
<v:imagedata o:title="network" src="wordml://02000001.jpg"/>
</v:shape>
</w:pict>
Set a Heading and center it
<w:p>
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:t>Hello, World.</w:t>
</w:r>
<w:br/>
<w:r>
<w:t>How are you, today?</w:t>
</w:r>
</w:p>
For more information regarding WordML refer this link.
http://rep.oio.dk/microsoft.com/officeschemas/wordprocessingml_article.htm

add new column to install script in magento CMS Page

So i am down to the last bit of my module and it's really annoying i can't get it to add a new column to the CMS_PAGE table.
This is what i have so far:
/app/code/local/Damian/CMS/etc/config.xml
<?xml version="1.0"?>
<config>
<modules>
<damian_cms>
<version>0.1.0</version> <!-- Version of module -->
</damian_cms>
</modules>
<global>
<models>
<damian_cms>
<class>Damian_CMS_Model</class>
<resourceModel>cms_mysql4</resourceModel>
</damian_cms>
</models>
<events>
<adminhtml_cms_page_edit_tab_content_prepare_form>
<observers>
<damian_page_edit_tab_content>
<type>singleton</type>
<class>Damian_CMS_Model_Observer</class>
<method>cmsField</method>
</damian_page_edit_tab_content>
</observers>
</adminhtml_cms_page_edit_tab_content_prepare_form>
<cms_page_prepare_save>
<observers>
<damian_cms_save_page>
<type>singleton</type>
<class>Damian_CMS_Model_Observer</class>
<method>savePage</method>
</damian_cms_save_page>
</observers>
</cms_page_prepare_save>
</events>
<resources>
<damian_cms_setup>
<setup>
<module>damian_cms</module>
<class>Damian_CMS_Model_Resource_Setup</class>
</setup>
<connection>
<use>core_setup</use>
</connection>
</damian_cms_setup>
<cms_write> <!-- It gives the write permission to db -->
<connection>
<use>core_write</use>
</connection>
</cms_write>
<cms_read> <!-- It gives the read permission from db -->
<connection>
<use>core_read</use>
</connection>
</cms_read>
</resources>
</global>
</config>
/app/code/local/Damian/CMS/Model/Resource/Setup.php
<?php
class Damian_CMS_Model_Resource_Setup extends Mage_Core_Model_Resource_Setup {
}
/app/code/local/Damian/CMS/sql/cms_setup/mysql-install-0.1.0.php
<?php
$installer = $this;
/* #var $installer Mage_Core_Model_Resource_Setup */
echo 'Running This Upgrade:';
die("Exit for now");
$installer->startSetup();
$tableName = $installer->getTable('cms_page');
$installer->getConnection()->addColumn($tableName, 'cms_sitemap', array(
'nullable' => true,
'length' => 255,
'default' => 1,
'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
'comment' => 'added from extension Damian CMS'
));
$installer->endSetup();
I haven't added the rest becuase it all seems to work, but i neeed this install script to work so i can put it into production on the live server, this is local and i have access to my own MYSQL database, But on the live servers i won't have access to the MYSQL database so i have to get this script to work.
Thanks for your help :)
ok so i got it to work!
I had to change the name of the module to match what i had to this
<modules>
<Damian_CmsUpdate> <!-- Name had to change to match folder name -->
<version>0.1</version>
</Damian_CmsUpdate>
</modules>
and then had to update the setup in the config.xml to this
<! -.....- >
<setup>
<module>Damian_CmsUpdate</module>
<class>Damian_CmsUpdate_Model_Resource_Mysql4_Setup</class>
</setup>
<! -......- >

How to create bullet lists in WordML?

I have the following WordML snippet which works well for numbered lists :
<w:wordDocument xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml">
<w:lists>
<w:listDef w:listDefId="1">
<w:lvl w:ilvl="0">
<w:start w:val="1" />
<w:lvlText w:val="%1." />
<w:pPr>
<w:ind w:left="720" w:hanging="360" />
</w:pPr>
</w:lvl>
<w:lvl w:ilvl="1">
<w:start w:val="1" />
<w:lvlText w:val="%2." />
<w:pPr>
<w:ind w:left="1080" w:hanging="360" />
</w:pPr>
</w:lvl>
</w:listDef>
<w:list w:ilfo="2">
<w:ilst w:val="1" />
</w:list>
</w:lists>
<w:body>
<wx:sect>
<w:p>
<w:pPr>
<w:listPr>
<w:ilvl w:val="0" />
<w:ilfo w:val="2" />
</w:listPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Item 1</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:listPr>
<w:ilvl w:val="1" />
<w:ilfo w:val="2" />
</w:listPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Item 1.1</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:listPr>
<w:ilvl w:val="1" />
<w:ilfo w:val="2" />
</w:listPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Item 1.2</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:listPr>
<w:ilvl w:val="0" />
<w:ilfo w:val="2" />
</w:listPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Item 2</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:listPr>
<w:ilvl w:val="1" />
<w:ilfo w:val="2" />
</w:listPr>
</w:pPr>
<w:r>
<w:t xml:space="preserve">Item 2.2</w:t>
</w:r>
</w:p>
</wx:sect>
</w:body>
</w:wordDocument>
However, I can't figure out how to create a bulleted list. I have seen lvlPicBulletId but I don't understand how to use it. Anybody knows how to do it?
Thanks.
Turns out that bullets are simply characters in specific fonts. For example, here is the lvl element for a filled circle :
<w:lvl w:ilvl="0">
<w:lvlText w:val="ยท" />
<w:rPr>
<w:rFonts w:ascii="Symbol" w:h-ansi="Symbol" w:hint="default" />
</w:rPr>
<w:pPr>
<w:ind w:left="720" w:hanging="360" />
</w:pPr>
</w:lvl>
A bulleted list in WordML is defined by the level NFC value of 23.
<w:listDef>
<w:lvl>
<w:nfc w:val="23"/>
</w:lvl>
<w:listDef>
You can then define the symbol used for the bullet by setting the w:lvlText value.
<w:listDef>
<w:lvl>
<w:lvlText w:val="o"/>
</w:lvl>
</w:listDef>
The following URL will take you to the NFC elements reference page on MSDN but it does not provide very much detail.
http://msdn.microsoft.com/en-us/library/office/ee364387(v=office.11).aspx
Hope that helps! :-)