"Fossies" - the Fresh Open Source Software Archive

Member "node-v12.18.4-win-x86/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py" (14 Feb 2020, 5153 Bytes) of package /windows/www/node-v12.18.4-win-x86.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 # Copyright (c) 2011 Google Inc. All rights reserved.
    2 # Use of this source code is governed by a BSD-style license that can be
    3 # found in the LICENSE file.
    4 
    5 import re
    6 import os
    7 import locale
    8 from functools import reduce
    9 
   10 
   11 def XmlToString(content, encoding='utf-8', pretty=False):
   12   """ Writes the XML content to disk, touching the file only if it has changed.
   13 
   14   Visual Studio files have a lot of pre-defined structures.  This function makes
   15   it easy to represent these structures as Python data structures, instead of
   16   having to create a lot of function calls.
   17 
   18   Each XML element of the content is represented as a list composed of:
   19   1. The name of the element, a string,
   20   2. The attributes of the element, a dictionary (optional), and
   21   3+. The content of the element, if any.  Strings are simple text nodes and
   22       lists are child elements.
   23 
   24   Example 1:
   25       <test/>
   26   becomes
   27       ['test']
   28 
   29   Example 2:
   30       <myelement a='value1' b='value2'>
   31          <childtype>This is</childtype>
   32          <childtype>it!</childtype>
   33       </myelement>
   34 
   35   becomes
   36       ['myelement', {'a':'value1', 'b':'value2'},
   37          ['childtype', 'This is'],
   38          ['childtype', 'it!'],
   39       ]
   40 
   41   Args:
   42     content:  The structured content to be converted.
   43     encoding: The encoding to report on the first XML line.
   44     pretty: True if we want pretty printing with indents and new lines.
   45 
   46   Returns:
   47     The XML content as a string.
   48   """
   49   # We create a huge list of all the elements of the file.
   50   xml_parts = ['<?xml version="1.0" encoding="%s"?>' % encoding]
   51   if pretty:
   52     xml_parts.append('\n')
   53   _ConstructContentList(xml_parts, content, pretty)
   54 
   55   # Convert it to a string
   56   return ''.join(xml_parts)
   57 
   58 
   59 def _ConstructContentList(xml_parts, specification, pretty, level=0):
   60   """ Appends the XML parts corresponding to the specification.
   61 
   62   Args:
   63     xml_parts: A list of XML parts to be appended to.
   64     specification:  The specification of the element.  See EasyXml docs.
   65     pretty: True if we want pretty printing with indents and new lines.
   66     level: Indentation level.
   67   """
   68   # The first item in a specification is the name of the element.
   69   if pretty:
   70     indentation = '  ' * level
   71     new_line = '\n'
   72   else:
   73     indentation = ''
   74     new_line = ''
   75   name = specification[0]
   76   if not isinstance(name, str):
   77     raise Exception('The first item of an EasyXml specification should be '
   78                     'a string.  Specification was ' + str(specification))
   79   xml_parts.append(indentation + '<' + name)
   80 
   81   # Optionally in second position is a dictionary of the attributes.
   82   rest = specification[1:]
   83   if rest and isinstance(rest[0], dict):
   84     for at, val in sorted(rest[0].items()):
   85       xml_parts.append(' %s="%s"' % (at, _XmlEscape(val, attr=True)))
   86     rest = rest[1:]
   87   if rest:
   88     xml_parts.append('>')
   89     all_strings = reduce(lambda x, y: x and isinstance(y, str), rest, True)
   90     multi_line = not all_strings
   91     if multi_line and new_line:
   92       xml_parts.append(new_line)
   93     for child_spec in rest:
   94       # If it's a string, append a text node.
   95       # Otherwise recurse over that child definition
   96       if isinstance(child_spec, str):
   97        xml_parts.append(_XmlEscape(child_spec))
   98       else:
   99         _ConstructContentList(xml_parts, child_spec, pretty, level + 1)
  100     if multi_line and indentation:
  101       xml_parts.append(indentation)
  102     xml_parts.append('</%s>%s' % (name, new_line))
  103   else:
  104     xml_parts.append('/>%s' % new_line)
  105 
  106 
  107 def WriteXmlIfChanged(content, path, encoding='utf-8', pretty=False,
  108                       win32=False):
  109   """ Writes the XML content to disk, touching the file only if it has changed.
  110 
  111   Args:
  112     content:  The structured content to be written.
  113     path: Location of the file.
  114     encoding: The encoding to report on the first line of the XML file.
  115     pretty: True if we want pretty printing with indents and new lines.
  116   """
  117   xml_string = XmlToString(content, encoding, pretty)
  118   if win32 and os.linesep != '\r\n':
  119     xml_string = xml_string.replace('\n', '\r\n')
  120 
  121   default_encoding = locale.getdefaultlocale()[1]
  122   if default_encoding.upper() != encoding.upper():
  123     xml_string = xml_string.encode(encoding)
  124 
  125   # Get the old content
  126   try:
  127     f = open(path, 'r')
  128     existing = f.read()
  129     f.close()
  130   except:
  131     existing = None
  132 
  133   # It has changed, write it
  134   if existing != xml_string:
  135     f = open(path, 'wb')
  136     f.write(xml_string)
  137     f.close()
  138 
  139 
  140 _xml_escape_map = {
  141     '"': '&quot;',
  142     "'": '&apos;',
  143     '<': '&lt;',
  144     '>': '&gt;',
  145     '&': '&amp;',
  146     '\n': '&#xA;',
  147     '\r': '&#xD;',
  148 }
  149 
  150 
  151 _xml_escape_re = re.compile(
  152     "(%s)" % "|".join(map(re.escape, _xml_escape_map.keys())))
  153 
  154 
  155 def _XmlEscape(value, attr=False):
  156   """ Escape a string for inclusion in XML."""
  157   def replace(match):
  158     m = match.string[match.start() : match.end()]
  159     # don't replace single quotes in attrs
  160     if attr and m == "'":
  161       return m
  162     return _xml_escape_map[m]
  163   return _xml_escape_re.sub(replace, value)