Search code examples
c#xmlopenxmlopenxml-sdk

Styles Format Openxml


I am trying to build a document with Openxml,

when i add a style to the styles.xml and try to validate it, i get the following error

The element has unexpected child element 'http://schemas.openxmlformats.org/wordprocessingml/2006/main:rFonts'

here is the styles.xml:

<?xml version="1.0" encoding="UTF-8"?>
<w:styles xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:style w:customStyle="true" w:styleId="33" w:type="paragraph">
<w:name w:val="Heading 1"/>
<w:basedOn w:val="Normal"/>
<w:next w:val="Normal"/>
<w:rPr>
<w:color w:val="E32020" w:themeColor="light2"/>
<w:rFonts w:ascii="Calibri Light"/>
<w:sz w:val="32"/>
</w:rPr>
</w:style>
</w:styles>

Can someone help me understand whats wrong with my style.


Solution

  • This seems to be an error on the part of the Open XML validator, which you can ignore. If you look at the specification of the w:rPr element, w:rFonts is clearly a permitted child element of w:rPr. If you open the document in Word (as hinted by Cindy) and Word does not complain, you are fine.

    As Cindy also noted, your style definition has the issue that you are using Heading 1 as the style name. Since the built-in style's name is heading 1 (note the lowercase "h"), this would even work on the Open XML level (but you might not see your exact style name in Word, because Word will use "Heading 1" as the display name at least if your display language is English). However, Word would change your w:styleId value (which is "33" in your example). The rule is that the w:styleId value is a function of the w:name value. For example, if your style's w:name value is "My Style Name", the corresponding w:styleId value should be "MyStyleName". At least this is what Word will use once you save the document in Word.

    For built-in styles, the names are localized and do not exactly follow that rule. For example, the built-in "Heading 1" style's w:name value is "heading 1" and the w:styleId value is "Heading1" (note the uppercase "H") if you have chosen English as the display language. If you have chosen German or French, for example, the w:styleId values would be "berschrift1" or "Titre1", respectively. The German w:styleId value would actually have to be "Überschrift1" (note the umlaut), but Word simply strips umlaut characters from w:styleId values.

    In your case, if you stick to "Heading 1" as the style name, Word could not use "Heading1" (in the English version) and would append a character to the w:styleId value to be able to differentiate between those styles.

    Assuming you have English as your display language, to modify the built-in "Heading 1" style, you will need something like the following, which in this example is simply the standard "Heading 1" style as used by Word in the Normal.dotx template.

      <w:style w:type="paragraph" w:styleId="Heading1">
        <w:name w:val="heading 1"/>
        <w:basedOn w:val="Normal"/>
        <w:next w:val="Normal"/>
        <w:link w:val="Heading1Char"/>
        <w:uiPriority w:val="9"/>
        <w:qFormat/>
        <w:rsid w:val="008A559F"/>
        <w:pPr>
          <w:keepNext/>
          <w:keepLines/>
          <w:spacing w:before="240" w:after="0"/>
          <w:outlineLvl w:val="0"/>
        </w:pPr>
        <w:rPr>
          <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi"/>
          <w:color w:val="2F5496" w:themeColor="accent1" w:themeShade="BF"/>
          <w:sz w:val="32"/>
          <w:szCs w:val="32"/>
        </w:rPr>
      </w:style>
    

    Note again that the w:name value is "heading 1" with a lowercase "h". Also note the w:rFonts element, showing that the validator is wrong.