Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  xml_diff.py

  Sprache: Python
 

# Copyright (C) 2020 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""A library containing functions for diffing XML elements."""
import textwrap
from typing import Any, Callable, Dict, Set
import xml.etree.ElementTree as ET
import dataclasses

Element = ET.Element

_INDENT = (' ' * 2)


@dataclasses.dataclass
class Change:
  value_from: str
  value_to: str

  def __repr__(self):
    return f'{self.value_from} -> {self.value_to}'


@dataclasses.dataclass
class ChangeMap:
  """A collection of changes broken down by added, removed and modified.

  Attributes:
    added: A dictionary of string identifiers to the added string.
    removed: A dictionary of string identifiers to the removed string.
    modified: A dictionary of string identifiers to the changed object.
  """
  added: Dict[str, str] = dataclasses.field(default_factory=dict)
  removed: Dict[str, str] = dataclasses.field(default_factory=dict)
  modified: Dict[str, Any] = dataclasses.field(default_factory=dict)

  def __repr__(self):
    ret_str = ''
    if self.added:
      ret_str += 'Added:\n'
      for value in self.added.values():
        ret_str += textwrap.indent(str(value) + '\n', _INDENT)
    if self.removed:
      ret_str += 'Removed:\n'
      for value in self.removed.values():
        ret_str += textwrap.indent(str(value) + '\n', _INDENT)
    if self.modified:
      ret_str += 'Modified:\n'
      for name, value in self.modified.items():
        ret_str += textwrap.indent(name + ':\n', _INDENT)
        ret_str += textwrap.indent(str(value) + '\n', _INDENT * 2)
    return ret_str

  def __bool__(self):
    return bool(self.added) or bool(self.removed) or bool(self.modified)


def element_string(e: Element) -> str:
  return ET.tostring(e).decode(encoding='UTF-8').strip()


def attribute_changes(e1: Element, e2: Element,
                      ignored_attrs: Set[str]) -> ChangeMap:
  """Get the changes in attributes between two XML elements.

  Arguments:
    e1: the first xml element.
    e2: the second xml element.
    ignored_attrs: a set of attribute names to ignore changes.

  Returns:
    A ChangeMap of attribute changes. Keyed by attribute name.
  """
  changes = ChangeMap()
  attributes = set(e1.keys()) | set(e2.keys())
  for attr in attributes:
    if attr in ignored_attrs:
      continue
    a1 = e1.get(attr)
    a2 = e2.get(attr)
    if a1 == a2:
      continue
    elif not a1:
      changes.added[attr] = a2 or ''
    elif not a2:
      changes.removed[attr] = a1
    else:
      changes.modified[attr] = Change(value_from=a1, value_to=a2)
  return changes


def compare_subelements(
    tag: str,
    p1: Element,
    p2: Element,
    ignored_attrs: Set[str],
    key_fn: Callable[[Element], str],
    diff_fn: Callable[[Element, Element, Set[str]], Any]) -> ChangeMap:
  """Get the changes between subelements of two parent elements.

  Arguments:
    tag: tag name for children element.
    p1: the base parent xml element.
    p2: the parent xml element to compare
    ignored_attrs: a set of attribute names to ignore changes.
    key_fn: Function that takes a subelement and returns a key
    diff_fn: Function that take two subelements and a set of ignored
      attributes, returns the differences

  Returns:
    A ChangeMap object of the changes.
  """
  changes = ChangeMap()
  group1 = {}
  for e1 in p1.findall(tag):
    group1[key_fn(e1)] = e1

  for e2 in p2.findall(tag):
    key = key_fn(e2)
    e1 = group1.pop(key, None)
    if e1 is None:
      changes.added[key] = element_string(e2)
    else:
      echange = diff_fn(e1, e2, ignored_attrs)
      if echange:
        changes.modified[key] = echange

  for name, e1 in group1.items():
    changes.removed[name] = element_string(e1)

  return changes

Messung V0.5 in Prozent
C=92 H=96 G=93

¤ Dauer der Verarbeitung: 0.19 Sekunden  (vorverarbeitet am  2026-06-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik