【问题标题】:Find and replace specific text within an attribute in XML using Python使用 Python 在 XML 中的属性中查找和替换特定文本
【发布时间】:2017-05-09 16:29:09
【问题描述】:

我有一个 XML 文件(下面的示例) - 我使用的是 Python 2.7

我想将所有出现的 stag 改为读取 prod。 “stag”一词位于 URL 中。我不想改变整个 url 只是单词 stag 的出现 - 请参阅示例:

url=http://stag/comp/rest/services/editor/hyd/MapServer

想改成:

url=http://prod/comp/rest/services/editor/hyd/MapServer

<Map FullExtent="-136163.9492,444360.64787994,-525467.175315,43020.05517682" InitialExtent="-32989.136772,6307.55418809,-4753.07696,5137.2783653">
<LayerList>
  <Items>
    <Item ID="17" />
    <Item ID="20" IsExpanded="true" Name="Reference Data" Visible="true">
      <Items>
        <Item ID="30" />
        <Item ID="34" VisibleInLayerList="false" />
        <Item ID="22" VisibleInLayerList="false" />
        <Item ID="41" VisibleInLayerList="false" />
        <Item ID="16" />
        <Item ID="37" />
        <Item ID="24" />
        <Item ID="39" />
        <Item ID="32" />
        <Item ID="28" />
        <Item ID="26" />
      </Items>
    </Item>
    <Item ID="19" IsExpanded="true" Name="Basemaps" Visible="true">
      <Items>
        <Item ID="12" />
        <Item ID="11" />
      </Items>
    </Item>
  </Items>
</LayerList>
<MapServices>
  <MapService ConnectionString="url=http://stag/comp/rest/services/editor/hyd/MapServer" DefaultAllowSymbolization="true" DisplayName="hydrants" Function="Operational" ID="17" ImageFormat="Png32" ImpersonateWithActor="false" IncludeCopyright="false" IncludeInLayerList="true" InstantSearch="false" InstantSearchAttachments="false" IsExpanded="true" MaximumScale="500" MinimumScale="7500" Opacity="1" OverrideTemporalSettings="false" PasswordEncrypted="false" ProviderInvariantName="Geocortex.Gis.Services.ArcGisServer.Rest" SearchNonTextFields="true" SupportedImageHeight="0" SupportedImageWidth="0" UseHttpAuthentication="false" Visible="true">
    <CachedServiceData />
    <Layers>
      <Layer AllowSymbolization="true" CanCopyFeature="true" DisplayName="Hydrants" FeatureDescription="&lt;div&gt;&lt;span style=&quot;font-family: Arial, Verdana; font-size: 13.3333px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; line-height: normal;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Hydrant ID: &lt;/span&gt;&lt;/span&gt;&lt;font face=&quot;Arial, Verdana&quot;&gt;&lt;span style=&quot;font-size: 13.3333px;&quot;&gt;{FIRE_HYDRANT_ID}&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;div style=&quot;font-family: Arial, Verdana; font-size: 10pt; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; line-height: normal;&quot;&gt;&lt;span style=&quot;font-size: 13.3333px; font-family: Arial, Verdana;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;br/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: Arial, Verdana; font-size: 10pt; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; line-height: normal;&quot;&gt;&lt;span style=&quot;font-size: 13.3333px; font-family: Arial, Verdana;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Work Order Number&lt;/span&gt;: {WORK_ORDER_NUM}&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: Arial, Verdana; font-size: 10pt; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; line-height: normal;&quot;&gt;&lt;span style=&quot;font-size: 13.3333px; font-family: Arial, Verdana;&quot;&gt;&lt;br/&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: Arial, Verdana; font-size: 10pt; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; line-height: normal;&quot;&gt;&lt;font face=&quot;Arial, Verdana&quot;&gt;&lt;span style=&quot;font-size: 13.3333px;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Make&lt;/span&gt;: {MAKE}&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;div style=&quot;font-family: Arial, Verdana; font-size: 10pt; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; line-height: normal;&quot;&gt;&lt;font face=&quot;Arial, Verdana&quot;&gt;&lt;span style=&quot;font-size: 13.3333px;&quot;&gt;&lt;br/&gt;&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;div style=&quot;font-family: Arial, Verdana; font-size: 10pt; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; line-height: normal;&quot;&gt;&lt;font face=&quot;Arial, Verdana&quot;&gt;&lt;span style=&quot;font-size: 13.3333px;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Elevation&lt;/span&gt;: {ELEVATION}&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;div style=&quot;font-family: Arial, Verdana; font-size: 10pt; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; line-height: normal;&quot;&gt;&lt;font face=&quot;Arial, Verdana&quot;&gt;&lt;span style=&quot;font-size: 13.3333px;&quot;&gt;&lt;br/&gt;&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;div style=&quot;font-family: Arial, Verdana; font-size: 10pt; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; line-height: normal;&quot;&gt;&lt;font face=&quot;Arial, Verdana&quot;&gt;&lt;span style=&quot;font-size: 13.3333px;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Hydrant Number&lt;/span&gt;: {HYDRANT_NUM}&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;div style=&quot;font-family: Arial, Verdana; font-size: 10pt; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; line-height: normal;&quot;&gt;&lt;font face=&quot;Arial, Verdana&quot;&gt;&lt;span style=&quot;font-size: 13.3333px;&quot;&gt;&lt;br/&gt;&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;div style=&quot;font-family: Arial, Verdana; font-size: 10pt; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; line-height: normal;&quot;&gt;&lt;font face=&quot;Arial, Verdana&quot;&gt;&lt;span style=&quot;font-size: 13.3333px;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Hydrant Size&lt;/span&gt;: {HYDRANT_SIZE}&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;div style=&quot;font-family: Arial, Verdana; font-size: 10pt; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; line-height: normal;&quot;&gt;&lt;font face=&quot;Arial, Verdana&quot;&gt;&lt;span style=&quot;font-size: 13.3333px;&quot;&gt;&lt;br/&gt;&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;&lt;div style=&quot;font-family: Arial, Verdana; font-size: 10pt; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; line-height: normal;&quot;&gt;&lt;font face=&quot;Arial, Verdana&quot;&gt;&lt;span style=&quot;font-size: 13.3333px;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Install Year&lt;/span&gt;: {INSTALL_YEAR}&lt;/span&gt;&lt;/font&gt;&lt;/div&gt;" FeatureLabel="&lt;b&gt;Fire Hydrant&lt;/b&gt;" Identifiable="true" IncludeInLayerList="true" IncludeInLegend="true" IsCatalogLayer="false" IsExpanded="true" LayerListID="30" Name="SJPWPUB.FIRE_HYDRANT" NativeID="0" Queryable="true" Searchable="true" ShowFeatureHyperlinks="ShowAll" ShowLabels="true" ShowMapTips="true" Snappable="true" SnappingEnabled="false" UnconfiguredFieldsCanSymbolizeClassBreaks="false" UnconfiguredFieldsCanSymbolizeUniqueValue="false" UnconfiguredFieldsSearchable="false" UnconfiguredFieldsVisible="false" UnconfiguredRelationshipsVisible="true" Visible="true">
        <Fields>
          <Field CanSymbolizeClassBreaks="false" CanSymbolizeUniqueValue="false" DisplayIndex="5" DisplayName="Hydrant Number" FocusField="false" Name="HYDRANT_NUM" Searchable="true" Visible="true" />
          <Field CanSymbolizeClassBreaks="false" CanSymbolizeUniqueValue="false" DisplayIndex="2" DisplayName="Work Order Number" FocusField="false" Name="WORK_ORDER_NUM" Searchable="false" Visible="true" />
          <Field CanSymbolizeClassBreaks="false" CanSymbolizeUniqueValue="false" DisplayIndex="3" DisplayName="Make" FocusField="false" Name="MAKE" Searchable="false" Visible="true" />
          <Field CanSymbolizeClassBreaks="false" CanSymbolizeUniqueValue="false" DisplayIndex="6" DisplayName="Hydrant Size" FocusField="false" Name="HYDRANT_SIZE" Searchable="false" Visible="true" />
          <Field CanSymbolizeClassBreaks="false" CanSymbolizeUniqueValue="false" DisplayIndex="7" DisplayName="Install Year" FocusField="false" Name="INSTALL_YEAR" Searchable="false" Visible="true" />
          <Field CanSymbolizeClassBreaks="false" CanSymbolizeUniqueValue="false" DisplayIndex="4" DisplayName="Elevation" FocusField="false" Name="ELEVATION" Searchable="false" Visible="true" />
          <Field CanSymbolizeClassBreaks="false" CanSymbolizeUniqueValue="false" DisplayIndex="1" DisplayName="Fire Hydrant ID" FocusField="false" Name="OBJECTID" Searchable="false" Visible="true" />
        </Fields>
      </Layer>
    </Layers>
  </MapService>
</Map>

我尝试了几种不同的方法,但似乎都不起作用。这是我最近的尝试:

Prod_xml = r"C:/Users/ba/Documents/temp/Prod/Projects/Site.xml"

import lxml.etree as ET

with open(Prod_xml, 'rb+') as f:
    tree = ET.parse(f)
    root = tree.getroot()
    for elem in root.getiterator():
       if elem.text:
          elem.text.replace('stag', 'prod')
       if elem.tail:
          elem.tail.replace('stag', 'prod')

f.seek(0)
f.write(ET.tostring(tree, encoding='UTF-8', xml_declaration=True))
f.truncate()

这不起作用。我没有收到任何错误,但 xml 文件没有改变。

关于如何做到这一点的任何想法?

更新

我想使用 ElementTree 选项,但是当我使用 xml.etree.ElementTree 脚本时出现以下错误(它还会完全删除我的 xml 文件中的数据):

Traceback (most recent call last):
  File "F:/Applications/Geocortex/MovingGeocortexFiles.py", line 56, in <module>
    ET.dump(f)
  File "C:\Python27\ArcGIS10.3\lib\xml\etree\ElementTree.py", line 1164, in dump
    elem.write(sys.stdout)
  File "C:\Python27\ArcGIS10.3\lib\xml\etree\ElementTree.py", line 817, in write
    self._root, encoding, default_namespace
  File "C:\Python27\ArcGIS10.3\lib\xml\etree\ElementTree.py", line 876, in _namespaces
    iterate = elem.getiterator # cET compatibility
AttributeError: 'file' object has no attribute 'getiterator'

【问题讨论】:

    标签: python xml


    【解决方案1】:

    我知道这可能过于简单化了问题,但这样做不是更容易:

    with open(filepath, 'r') as f:
        res = f.read().replace('http://stag', 'http://prod')
    
    with open(filepath,'w') as f:
        f.write(res)
    

    如果你坚持把它解析为XML,你可以这样做:

    import xml.etree.ElementTree as ET
    
    with open(filepath, 'r') as f:
        tree = ET.parse(f)
    
    for n in tree.findall(".//"):
        for a in n.attrib:
            n.attrib[a] = n.attrib[a].replace("stag", "prod")
    
    with open(filepath, 'w') as f:
        tree.write(f)
    

    【讨论】:

    • 这很完美!我发誓我最初尝试过这个并且考虑过这个问题,因为 xml 可能有点复杂。
    • 虽然这可能适用于这种特殊情况,但不要将 XML 视为文本文件。使用 DOM 处理解析和更新节点/属性值。您可以结束破坏格式良好的树,甚至尝试regex,这对于 X/HTML 文档来说是不明智的。
    • 我也添加了一个 XML 解决方案。
    • @LiranFunaro 我想使用 ElementTree 选项,但是当我使用 xml.etree.ElementTree 脚本时出现错误(它还完全删除了我的 xml 文件中的数据)。请参阅上面的更新
    • 对不起,我的错。我使用转储错误。试试我的修正。
    猜你喜欢
    • 2021-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 2019-10-16
    • 1970-01-01
    • 2011-06-12
    • 2020-08-02
    相关资源
    最近更新 更多