0

Certain xml specifications require a markup declaration to perform a task. One such example is below; a conditional to check a framework version in Wix

    <Condition Message="This application requires .NET Framework 4.6.2. Please install the .NET Framework then run this installer again.">
          <![CDATA[Installed OR WIX_IS_NETFRAMEWORK_462_OR_LATER_INSTALLED]]>
    </Condition>

While the condition is trivial to build an element for:

   def add_net462_prerequisite(self, parent):
        condition = ET.SubElement(
            parent,
            "Condition",
            Message="This application requires .NET Framework 4.6.2. "
                    "Please install the .NET Framework then run this installer again.",
        )

I can't seem to find a way to add a "markup declaration" to specify the line

<![CDATA[Installed OR WIX_IS_NETFRAMEWORK_462_OR_LATER_INSTALLED]]>

I've gone through the documentation of xml.etree.ElementTree and can't find anything about markup declarations; nor have I found anything via searching the web on markup declarations in that library or lxml's elementree.

A way to add raw text, a markup declaration, or another hack would be acceptable. I'm half considering re-reading the output file, locating the appropriate node and then adding the text programmatically, but I'm hoping it doesn't come to that.

Thank you for any assistance

Note: We're currently using wix 3.14; though this question is really regarding ElementTree.

EDIT: I've also attempted to use ElementTree.fromstring("<![CDATA[Installed OR WIX_IS_NETFRAMEWORK_462_OR_LATER_INSTALLED]]>"), which fails with a parse error.

Similarly, I've tried the below which, while it runs and builds an Element, that element fails to contain the <![CDATA[Installed OR WIX_IS_NETFRAMEWORK_462_OR_LATER_INSTALLED]]>

condition = ET.fromstring(
            '    <Condition Message="This application requires .NET Framework 4.6.2. '
            'Please install the .NET Framework then run this installer again.">'
            '        <![CDATA[Installed OR WIX_IS_NETFRAMEWORK_462_OR_LATER_INSTALLED]]>'
            '    </Condition>'
        )

Additional EDIT: It would seem that someone has posted a similar question before that I've finally located (and attempted to mark this as a duplicate of)

2 Answers2

0

Many don't like this, but I prefer building elements "by hand", so I would propose the answer below.

Note that it requires lxml, not ElementTree, if available:

Assuming your xml looks like this:

cond = """
<root>
 <Conditions>
   <Condition Message="no message">This is a condition; another one is next
    <![CDATA[some random string]]>
   </Condition>
 </Conditions>
</root>"

Try this:

from lxml import etree
parser = etree.XMLParser(strip_cdata=False)
doc = etree.XML(cond, parser)
#the 2nd parameter above is key
n_cond = """<Condition Message="This application requires .NET Framework 4.6.2. Please install the .NET Framework then run this installer again.">
          <![CDATA[Installed OR WIX_IS_NETFRAMEWORK_462_OR_LATER_INSTALLED]]>
    </Condition>"""

destination = doc.xpath('.//Conditions')[0]
final = etree.fromstring(n_cond,parser)
#again, note the 2nd parameter above
destination.append(final)
etree.indent(doc, space='  ', level=0)
#above requires python 3.9 or above
print(etree.tostring(doc).decode())

Output:

<root>
  <Conditions>
    <Condition Message="no message">This is a condition; another one is next
    <![CDATA[some random string]]>
   </Condition>
    <Condition Message="This application requires .NET Framework 4.6.2. Please install the .NET Framework then run this installer again.">
          <![CDATA[Installed OR WIX_IS_NETFRAMEWORK_462_OR_LATER_INSTALLED]]>
    </Condition>
  </Conditions>
</root>
Jack Fleeting
  • 24,385
  • 6
  • 23
  • 45
0

Nothing in that condition needs to be escaped, so you can specify it as normal inner text.

Bob Arnson
  • 21,377
  • 2
  • 40
  • 47
  • Do you mind expanding on this answer? There is not "inner text" method in ElementTree, and the `text` and `tail` methods are both `Element`s, which would mean I have the same issue since this string does not conform to an Element's requirements (e.g. a tag, a special `<!` and similar) – user1765812 Jun 08 '23 at 12:08
  • `text` is a string and you don't need the `CDATA` because the inner text doesn't need to be escaped. – Bob Arnson Jun 08 '23 at 14:33