通过 python 将 SLD 从 1.1 转换为 1.0
Converting SLD from 1.1 to 1.0 via python
我目前正在尝试通过编写 python 脚本将 SLD(一种 XML)从一个版本转换为另一个版本。近两个星期以来,我一直在努力解决这个问题,但进展甚微。
我是 python 的新手,非常感谢任何建议!
基本上,我需要把这个……
<?xml version="1.0" encoding="ISO-8859-1"?>
<StyledLayerDescriptor version="1.1.0" xmlns="http://www.opengis.net/sld"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xlink="http://www.w3.org/1999/xlink"
xsi:schemaLocation="http://www.opengis.net/sld
http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd"
xmlns:se="http://www.opengis.net/se">
<NamedLayer>
<se:Name>Custom_Landuse</se:Name>
<se:Description>
<se:Title>Custom_Landuse</se:Title>
<se:Abstract>A Land Use style</se:Abstract>
</se:Description>
<UserStyle>
<se:Name>County Electoral Division</se:Name>
<se:FeatureTypeStyle>
<se:Rule>
<se:Name>Woods</se:Name>
<ogc:Filter>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>AREA_CODE</ogc:PropertyName>
<ogc:Literal>CED</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>
<se:MinScaleDenominator>65000</se:MinScaleDenominator>
<se:MaxScaleDenominator>150000</se:MaxScaleDenominator>
<se:PolygonSymbolizer>
<se:Name>Woods</se:Name>
<se:Fill>
<se:SvgParameter name="fill">#228B22</se:SvgParameter>
<se:SvgParameter name="fill-opacity">0</se:SvgParameter>
</se:Fill>
<se:Stroke>
<se:SvgParameter name="stroke">#ADFF2F</se:SvgParameter>
<se:SvgParameter name="stroke-opacity"></se:SvgParameter>
<se:SvgParameter name="stroke-width">1.4</se:SvgParameter>
<se:SvgParameter name="stroke-linejoin">round</se:SvgParameter>
<se:SvgParameter name="stroke-linecap">round</se:SvgParameter>
</se:Stroke>
</se:PolygonSymbolizer>
<se:TextSymbolizer>
<se:Name>Woods</se:Name>
<se:Label>
<ogc:PropertyName>NAME</ogc:PropertyName>
</se:Label>
<se:Font>
<se:SvgParameter name="font-family">Sans-Serif</se:SvgParameter>
<se:SvgParameter name="font-style">normal</se:SvgParameter>
<se:SvgParameter name="font-size">20</se:SvgParameter>
<se:SvgParameter name="font-weight">bold</se:SvgParameter>
</se:Font>
<se:Fill>
<se:SvgParameter name="fill">#ADFF2F</se:SvgParameter>
</se:Fill>
</se:TextSymbolizer>
</se:Rule>
<se:Rule>
<se:Name>Grass</se:Name>
<ogc:Filter>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>AREA_CODE</ogc:PropertyName>
<ogc:Literal>CED</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>
<se:MinScaleDenominator>65000</se:MinScaleDenominator>
<se:MaxScaleDenominator>150000</se:MaxScaleDenominator>
<se:PolygonSymbolizer>
<se:Name>Grass</se:Name>
<se:Fill>
<se:SvgParameter name="fill">#90EE90</se:SvgParameter>
<se:SvgParameter name="fill-opacity">0</se:SvgParameter>
</se:Fill>
<se:Stroke>
<se:SvgParameter name="stroke">#6B8E23</se:SvgParameter>
<se:SvgParameter name="stroke-opacity"></se:SvgParameter>
<se:SvgParameter name="stroke-width">1.4</se:SvgParameter>
<se:SvgParameter name="stroke-linejoin">round</se:SvgParameter>
<se:SvgParameter name="stroke-linecap">round</se:SvgParameter>
</se:Stroke>
</se:PolygonSymbolizer>
<se:TextSymbolizer>
<se:Name>Grass</se:Name>
<se:Label>
<ogc:PropertyName>NAME</ogc:PropertyName>
</se:Label>
<se:Font>
<se:SvgParameter name="font-family">Sans-Serif</se:SvgParameter>
<se:SvgParameter name="font-style">normal</se:SvgParameter>
<se:SvgParameter name="font-size">20</se:SvgParameter>
<se:SvgParameter name="font-weight">bold</se:SvgParameter>
</se:Font>
<se:Fill>
<se:SvgParameter name="fill">#6B8E23</se:SvgParameter>
</se:Fill>
</se:TextSymbolizer>
</se:Rule>
</se:FeatureTypeStyle>
</UserStyle>
进入这个
<?xml version="1.0" encoding="UTF-8"?>
<StyledLayerDescriptor version="1.0.0" xmlns="http://www.opengis.net/sld"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:gml="http://www.opengis.net/gml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xlink="http://www.w3.org/1999/xlink"
xsi:schemaLocation="http://www.opengis.net/sld
http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd">
<NamedLayer>
<Name>Custom_Landuse</Name>
<UserStyle>
<Name>Land Use</Name>
<FeatureTypeStyle>
<Rule>
<Name>Woods</Name>
<Title>Woods - 1:65,000 to 1:150,000</Title>
<Abstract>A Land Use style</Abstract>
<ogc:Filter>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>AREA_CODE</ogc:PropertyName>
<ogc:Literal>CED</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>
<MinScaleDenominator>65000</MinScaleDenominator>
<MaxScaleDenominator>150000</MaxScaleDenominator>
<PolygonSymbolizer>
<Fill>
<CssParameter name="fill">#228B22</CssParameter>
<CssParameter name="fill-opacity">1</CssParameter>
</Fill>
<Stroke>
<CssParameter name="stroke">#ADFF2F</CssParameter>
<CssParameter name="stroke-opacity"></CssParameter>
<CssParameter name="stroke-width">1.4</CssParameter>
<CssParameter name="stroke-linejoin">round</CssParameter>
<CssParameter name="stroke-linecap">round</CssParameter>
</Stroke>
</PolygonSymbolizer>
<TextSymbolizer>
<Label>
<ogc:PropertyName>NAME</ogc:PropertyName>
</Label>
<Font>
<CssParameter name="font-family">Sans-Serif</CssParameter>
<CssParameter name="font-style">normal</CssParameter>
<CssParameter name="font-size">20</CssParameter>
<CssParameter name="font-weight">bold</CssParameter>
</Font>
<Fill>
<CssParameter name="fill">#ADFF2F</CssParameter>
</Fill>
</TextSymbolizer>
</Rule>
<Rule>
<Name>Grass</Name>
<Title>Grass - 1:65,000 to 1:150,000</Title>
<Abstract>A Land Use style</Abstract>
<ogc:Filter>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>AREA_CODE</ogc:PropertyName>
<ogc:Literal>CED</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>
<MinScaleDenominator>65000</MinScaleDenominator>
<MaxScaleDenominator>150000</MaxScaleDenominator>
<PolygonSymbolizer>
<Fill>
<CssParameter name="fill">#90EE90</CssParameter>
<CssParameter name="fill-opacity">1</CssParameter>
</Fill>
<Stroke>
<CssParameter name="stroke">#6B8E23</CssParameter>
<CssParameter name="stroke-opacity"></CssParameter>
<CssParameter name="stroke-width">1.4</CssParameter>
<CssParameter name="stroke-linejoin">round</CssParameter>
<CssParameter name="stroke-linecap">round</CssParameter>
</Stroke>
</PolygonSymbolizer>
<TextSymbolizer>
<Label>
<ogc:PropertyName>NAME</ogc:PropertyName>
</Label>
<Font>
<CssParameter name="font-family">Sans-Serif</CssParameter>
<CssParameter name="font-style">normal</CssParameter>
<CssParameter name="font-size">20</CssParameter>
<CssParameter name="font-weight">bold</CssParameter>
</Font>
<Fill>
<CssParameter name="fill">#6B8E23</CssParameter>
</Fill>
</TextSymbolizer>
</Rule>
</FeatureTypeStyle>
</UserStyle>
我目前有这个代码
import xml.etree.ElementTree as ET
from lxml import etree
# Run once per file
StyledLayerDescriptor = ET.Element("StyledLayerDescriptor",version="1.0", )
NamedLayer = ET.SubElement(StyledLayerDescriptor, "NamedLayer")
Name = ET.SubElement(NamedLayer, "Name")
Line_county_electoral_division_region"
UserStyle = ET.SubElement(NamedLayer, "UserStyle")
Name = ET.SubElement(UserStyle, "Name")"
FeatureTypeStyle = ET.SubElement(UserStyle, "FeatureTypeStyle")
# Run once per rule in file
Rule = ET.SubElement(FeatureTypeStyle, "Rule")
Name = ET.SubElement(Rule, "Name")
Line_county_electoral_division_region"
Title = ET.SubElement(Rule, "Title")
Abstract = ET.SubElement(Rule, "Abstract")
Filter = ET.SubElement(Rule, "Filter")
PropertyIsEqualTo = ET.SubElement(Filter, "PropertyIsEqualTo")
PropertyName = ET.SubElement(PropertyIsEqualTo, "PropertyName")
Literal = ET.SubElement(PropertyIsEqualTo, "Literal")
MinScaleDenominator = ET.SubElement(Rule, "MinScaleDenominator")
MaxScaleDenominator = ET.SubElement(Rule, "MaxScaleDenominator")
PolygonSymbolizer = ET.SubElement(Rule, "PolygonSymbolizer")
Fill = ET.SubElement(PolygonSymbolizer, "Fill")
Stroke = ET.SubElement(PolygonSymbolizer, "Stroke")
TextSymbolizer = ET.SubElement(Rule, "PolygonSymbolizer")
Label = ET.SubElement(TextSymbolizer, "Label")
PropertyName = ET.SubElement(Label, "PropertyName")
Front = ET.SubElement(TextSymbolizer, "Front")
Fill = ET.SubElement(TextSymbolizer, "Fill")
ET.SubElement(Fill, "CssParameter", name="fill")
ET.SubElement(Fill, "CssParameter", name="fill-opacity")
ET.SubElement(Stroke, "CssParameter", name="stroke")
ET.SubElement(Stroke, "CssParameter", name="stroke-opacity")
ET.SubElement(Stroke, "CssParameter", name="stroke-width")
ET.SubElement(Stroke, "CssParameter", name="stroke-linejoin")"
ET.SubElement(Stroke, "CssParameter", name="stroke-linecap")
ET.SubElement(Front, "CssParameter", name="font-family")
ET.SubElement(Front, "CssParameter", name="font-style")
ET.SubElement(Front, "CssParameter", name="font-size")
ET.SubElement(Front, "CssParameter", name="font-weight")
ET.SubElement(Fill, "CssParameter", name="fill")
Output = ET.ElementTree(StyledLayerDescriptor)
Output.write("SLD_Test.xml", xml_declaration=True, encoding='UTF-8')
parser = etree.XMLParser(remove_blank_text=True)
tree = etree.parse("SLD_Test.xml", parser)
tree.write("SLD_Test.xml", pretty_print=True)
此代码用于生成打印 xml 树
我不只是想更改名称空间,而是要重新格式化 xml 的结构,例如 1.0 版无法识别,但在 .
下需要一些数据
我不是在寻找完整的解决方案,因为我正试图掌握 python 和 XML。任何帮助都会很棒!甚至有用教程的链接
根据我从问题中收集到的信息,该任务涉及进行以下更改:
- 使用相同的本地名称映射 http://www.opengis.net/se elements to http://www.opengis.net/sld
- 将
CssParameter
元素更改为 SvgParameter
,保留属性
- 移除 xmlns:gml="http://www.opengis.net/gml"
- 将 ISO-8859-1 转换为 UTF-8
你的问题中有一些词被遗漏了,所以我没有完全理解所有的规则。在任何情况下,您都需要仔细检查 SLD 1.1 和 1.0 之间的差异,以确保您对这些差异制定了适当的规则。不要忘记,您可以通过不为输入文件未使用的差异编写规则来作弊。
这是一个简短的 Python 程序 (sld11-10.py
),它从输入中读取每个 XML 文件
目录,然后创建一个输出目录并写入一个相同的
相同目录中具有相同文件名的目录结构,
但内容已按照描述进行了转换。
#!/usr/bin/env python3
from lxml import etree
import os
import sys
sld10 = etree.XMLSchema(
etree.parse("http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd"))
sld11 = etree.XMLSchema(
etree.parse("http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd"))
transform = etree.XSLT(etree.parse("sld11-10.xsl"))
def walk(sour_dir: str, dest_dir: str) -> None:
os.mkdir(dest_dir)
for item in os.listdir(sour_dir):
sour_path = os.path.join(sour_dir, item)
dest_path = os.path.join(dest_dir, item)
if os.path.isdir(sour_path):
walk(sour_path, dest_path)
else:
sour_doc = etree.parse(sour_path)
if not sld11.validate(sour_doc):
print(sour_path, sld11.error_log.last_error)
dest_doc = transform(sour_doc)
if not sld10.validate(dest_doc):
print(dest_path, sld10.error_log.last_error)
dest_doc.write(dest_path,
pretty_print=True, xml_declaration=True, encoding="UTF-8")
return None
if __name__ == "__main__":
walk(sys.argv[1], sys.argv[2])
这里是引用的 XSLT 文件sld11-10.xsl
:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:se="http://www.opengis.net/se"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sld="http://www.opengis.net/sld"
exclude-result-prefixes="sld se">
<xsl:output encoding="UTF-8"/>
<!--
Chanage the version and the schemaLocation values
-->
<xsl:template match="/sld:StyledLayerDescriptor">
<StyledLayerDescriptor xmlns="http://www.opengis.net/sld"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:gml="http://www.opengis.net/gml">
<xsl:apply-templates select="@*"/>
<xsl:attribute name="version">1.0.0</xsl:attribute>
<xsl:attribute name="xsi:schemaLocation"
namespace="http://www.w3.org/2001/XMLSchema-instance">
<xsl:text>http://www.opengis.net/sld </xsl:text>
<xsl:text>http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd</xsl:text>
</xsl:attribute>
<xsl:apply-templates/>
</StyledLayerDescriptor>
</xsl:template>
<!--
Map SvgParameter elements in the http://www.opengis.net/se namespace
to CssParameter in the http://www.opengis.net/sld namespace
-->
<xsl:template match="se:SvgParameter">
<xsl:element name="CssParameter" namespace="http://www.opengis.net/sld">
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<!--
Map remaining http://www.opengis.net/se elements and attributes
to the http://www.opengis.net/sld namespace
-->
<xsl:template match="se:*">
<xsl:element name="{local-name()}" namespace="http://www.opengis.net/sld">
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<!--
Preserve all other elements and attributes
-->
<xsl:template match="*|@*">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<!--
Preserve processing instructuions and comments
-->
<xsl:template match="processing-instruction()|comment()">
<xsl:copy>.</xsl:copy>
</xsl:template>
</xsl:stylesheet>
if name == "main": walk(sys.argv[1], sys.argv[2]
部分的意思是
当您从命令行 运行 程序时,它将使用第一个
两个命令行参数作为 walk 例程的输入。例如,
假设您的 sld11-10.py
、sld11-10.xsl
和 input_directory
桌面,然后说input_directory
包含这样的文件
input_directory
file1.xml
file2.xml
subdirectory
file3.xml
然后,假设您没有名为 output_directory
的目录,您
可以运行这样的文件吗
sld11-10.py input_directory output_directory
该程序将创建具有以下结构的 output_direcory
:
output_directory
file1.xml
file2.xml
subdirectory
file3.xml
input_directory
和output_directory
的区别在于
output_directory
中的 XML 个文件将经过 XSLT 转换。
另外,请注意,在转换过程中,有关
XML 文件的有效性,SLD 1.0 和 SLD 1.1 都将被写入
过程中的屏幕。
我目前正在尝试通过编写 python 脚本将 SLD(一种 XML)从一个版本转换为另一个版本。近两个星期以来,我一直在努力解决这个问题,但进展甚微。
我是 python 的新手,非常感谢任何建议!
基本上,我需要把这个……
<?xml version="1.0" encoding="ISO-8859-1"?>
<StyledLayerDescriptor version="1.1.0" xmlns="http://www.opengis.net/sld"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xlink="http://www.w3.org/1999/xlink"
xsi:schemaLocation="http://www.opengis.net/sld
http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd"
xmlns:se="http://www.opengis.net/se">
<NamedLayer>
<se:Name>Custom_Landuse</se:Name>
<se:Description>
<se:Title>Custom_Landuse</se:Title>
<se:Abstract>A Land Use style</se:Abstract>
</se:Description>
<UserStyle>
<se:Name>County Electoral Division</se:Name>
<se:FeatureTypeStyle>
<se:Rule>
<se:Name>Woods</se:Name>
<ogc:Filter>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>AREA_CODE</ogc:PropertyName>
<ogc:Literal>CED</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>
<se:MinScaleDenominator>65000</se:MinScaleDenominator>
<se:MaxScaleDenominator>150000</se:MaxScaleDenominator>
<se:PolygonSymbolizer>
<se:Name>Woods</se:Name>
<se:Fill>
<se:SvgParameter name="fill">#228B22</se:SvgParameter>
<se:SvgParameter name="fill-opacity">0</se:SvgParameter>
</se:Fill>
<se:Stroke>
<se:SvgParameter name="stroke">#ADFF2F</se:SvgParameter>
<se:SvgParameter name="stroke-opacity"></se:SvgParameter>
<se:SvgParameter name="stroke-width">1.4</se:SvgParameter>
<se:SvgParameter name="stroke-linejoin">round</se:SvgParameter>
<se:SvgParameter name="stroke-linecap">round</se:SvgParameter>
</se:Stroke>
</se:PolygonSymbolizer>
<se:TextSymbolizer>
<se:Name>Woods</se:Name>
<se:Label>
<ogc:PropertyName>NAME</ogc:PropertyName>
</se:Label>
<se:Font>
<se:SvgParameter name="font-family">Sans-Serif</se:SvgParameter>
<se:SvgParameter name="font-style">normal</se:SvgParameter>
<se:SvgParameter name="font-size">20</se:SvgParameter>
<se:SvgParameter name="font-weight">bold</se:SvgParameter>
</se:Font>
<se:Fill>
<se:SvgParameter name="fill">#ADFF2F</se:SvgParameter>
</se:Fill>
</se:TextSymbolizer>
</se:Rule>
<se:Rule>
<se:Name>Grass</se:Name>
<ogc:Filter>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>AREA_CODE</ogc:PropertyName>
<ogc:Literal>CED</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>
<se:MinScaleDenominator>65000</se:MinScaleDenominator>
<se:MaxScaleDenominator>150000</se:MaxScaleDenominator>
<se:PolygonSymbolizer>
<se:Name>Grass</se:Name>
<se:Fill>
<se:SvgParameter name="fill">#90EE90</se:SvgParameter>
<se:SvgParameter name="fill-opacity">0</se:SvgParameter>
</se:Fill>
<se:Stroke>
<se:SvgParameter name="stroke">#6B8E23</se:SvgParameter>
<se:SvgParameter name="stroke-opacity"></se:SvgParameter>
<se:SvgParameter name="stroke-width">1.4</se:SvgParameter>
<se:SvgParameter name="stroke-linejoin">round</se:SvgParameter>
<se:SvgParameter name="stroke-linecap">round</se:SvgParameter>
</se:Stroke>
</se:PolygonSymbolizer>
<se:TextSymbolizer>
<se:Name>Grass</se:Name>
<se:Label>
<ogc:PropertyName>NAME</ogc:PropertyName>
</se:Label>
<se:Font>
<se:SvgParameter name="font-family">Sans-Serif</se:SvgParameter>
<se:SvgParameter name="font-style">normal</se:SvgParameter>
<se:SvgParameter name="font-size">20</se:SvgParameter>
<se:SvgParameter name="font-weight">bold</se:SvgParameter>
</se:Font>
<se:Fill>
<se:SvgParameter name="fill">#6B8E23</se:SvgParameter>
</se:Fill>
</se:TextSymbolizer>
</se:Rule>
</se:FeatureTypeStyle>
</UserStyle>
进入这个
<?xml version="1.0" encoding="UTF-8"?>
<StyledLayerDescriptor version="1.0.0" xmlns="http://www.opengis.net/sld"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:gml="http://www.opengis.net/gml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xlink="http://www.w3.org/1999/xlink"
xsi:schemaLocation="http://www.opengis.net/sld
http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd">
<NamedLayer>
<Name>Custom_Landuse</Name>
<UserStyle>
<Name>Land Use</Name>
<FeatureTypeStyle>
<Rule>
<Name>Woods</Name>
<Title>Woods - 1:65,000 to 1:150,000</Title>
<Abstract>A Land Use style</Abstract>
<ogc:Filter>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>AREA_CODE</ogc:PropertyName>
<ogc:Literal>CED</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>
<MinScaleDenominator>65000</MinScaleDenominator>
<MaxScaleDenominator>150000</MaxScaleDenominator>
<PolygonSymbolizer>
<Fill>
<CssParameter name="fill">#228B22</CssParameter>
<CssParameter name="fill-opacity">1</CssParameter>
</Fill>
<Stroke>
<CssParameter name="stroke">#ADFF2F</CssParameter>
<CssParameter name="stroke-opacity"></CssParameter>
<CssParameter name="stroke-width">1.4</CssParameter>
<CssParameter name="stroke-linejoin">round</CssParameter>
<CssParameter name="stroke-linecap">round</CssParameter>
</Stroke>
</PolygonSymbolizer>
<TextSymbolizer>
<Label>
<ogc:PropertyName>NAME</ogc:PropertyName>
</Label>
<Font>
<CssParameter name="font-family">Sans-Serif</CssParameter>
<CssParameter name="font-style">normal</CssParameter>
<CssParameter name="font-size">20</CssParameter>
<CssParameter name="font-weight">bold</CssParameter>
</Font>
<Fill>
<CssParameter name="fill">#ADFF2F</CssParameter>
</Fill>
</TextSymbolizer>
</Rule>
<Rule>
<Name>Grass</Name>
<Title>Grass - 1:65,000 to 1:150,000</Title>
<Abstract>A Land Use style</Abstract>
<ogc:Filter>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>AREA_CODE</ogc:PropertyName>
<ogc:Literal>CED</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>
<MinScaleDenominator>65000</MinScaleDenominator>
<MaxScaleDenominator>150000</MaxScaleDenominator>
<PolygonSymbolizer>
<Fill>
<CssParameter name="fill">#90EE90</CssParameter>
<CssParameter name="fill-opacity">1</CssParameter>
</Fill>
<Stroke>
<CssParameter name="stroke">#6B8E23</CssParameter>
<CssParameter name="stroke-opacity"></CssParameter>
<CssParameter name="stroke-width">1.4</CssParameter>
<CssParameter name="stroke-linejoin">round</CssParameter>
<CssParameter name="stroke-linecap">round</CssParameter>
</Stroke>
</PolygonSymbolizer>
<TextSymbolizer>
<Label>
<ogc:PropertyName>NAME</ogc:PropertyName>
</Label>
<Font>
<CssParameter name="font-family">Sans-Serif</CssParameter>
<CssParameter name="font-style">normal</CssParameter>
<CssParameter name="font-size">20</CssParameter>
<CssParameter name="font-weight">bold</CssParameter>
</Font>
<Fill>
<CssParameter name="fill">#6B8E23</CssParameter>
</Fill>
</TextSymbolizer>
</Rule>
</FeatureTypeStyle>
</UserStyle>
我目前有这个代码
import xml.etree.ElementTree as ET
from lxml import etree
# Run once per file
StyledLayerDescriptor = ET.Element("StyledLayerDescriptor",version="1.0", )
NamedLayer = ET.SubElement(StyledLayerDescriptor, "NamedLayer")
Name = ET.SubElement(NamedLayer, "Name")
Line_county_electoral_division_region"
UserStyle = ET.SubElement(NamedLayer, "UserStyle")
Name = ET.SubElement(UserStyle, "Name")"
FeatureTypeStyle = ET.SubElement(UserStyle, "FeatureTypeStyle")
# Run once per rule in file
Rule = ET.SubElement(FeatureTypeStyle, "Rule")
Name = ET.SubElement(Rule, "Name")
Line_county_electoral_division_region"
Title = ET.SubElement(Rule, "Title")
Abstract = ET.SubElement(Rule, "Abstract")
Filter = ET.SubElement(Rule, "Filter")
PropertyIsEqualTo = ET.SubElement(Filter, "PropertyIsEqualTo")
PropertyName = ET.SubElement(PropertyIsEqualTo, "PropertyName")
Literal = ET.SubElement(PropertyIsEqualTo, "Literal")
MinScaleDenominator = ET.SubElement(Rule, "MinScaleDenominator")
MaxScaleDenominator = ET.SubElement(Rule, "MaxScaleDenominator")
PolygonSymbolizer = ET.SubElement(Rule, "PolygonSymbolizer")
Fill = ET.SubElement(PolygonSymbolizer, "Fill")
Stroke = ET.SubElement(PolygonSymbolizer, "Stroke")
TextSymbolizer = ET.SubElement(Rule, "PolygonSymbolizer")
Label = ET.SubElement(TextSymbolizer, "Label")
PropertyName = ET.SubElement(Label, "PropertyName")
Front = ET.SubElement(TextSymbolizer, "Front")
Fill = ET.SubElement(TextSymbolizer, "Fill")
ET.SubElement(Fill, "CssParameter", name="fill")
ET.SubElement(Fill, "CssParameter", name="fill-opacity")
ET.SubElement(Stroke, "CssParameter", name="stroke")
ET.SubElement(Stroke, "CssParameter", name="stroke-opacity")
ET.SubElement(Stroke, "CssParameter", name="stroke-width")
ET.SubElement(Stroke, "CssParameter", name="stroke-linejoin")"
ET.SubElement(Stroke, "CssParameter", name="stroke-linecap")
ET.SubElement(Front, "CssParameter", name="font-family")
ET.SubElement(Front, "CssParameter", name="font-style")
ET.SubElement(Front, "CssParameter", name="font-size")
ET.SubElement(Front, "CssParameter", name="font-weight")
ET.SubElement(Fill, "CssParameter", name="fill")
Output = ET.ElementTree(StyledLayerDescriptor)
Output.write("SLD_Test.xml", xml_declaration=True, encoding='UTF-8')
parser = etree.XMLParser(remove_blank_text=True)
tree = etree.parse("SLD_Test.xml", parser)
tree.write("SLD_Test.xml", pretty_print=True)
此代码用于生成打印 xml 树
我不只是想更改名称空间,而是要重新格式化 xml 的结构,例如 1.0 版无法识别,但在 .
下需要一些数据我不是在寻找完整的解决方案,因为我正试图掌握 python 和 XML。任何帮助都会很棒!甚至有用教程的链接
根据我从问题中收集到的信息,该任务涉及进行以下更改:
- 使用相同的本地名称映射 http://www.opengis.net/se elements to http://www.opengis.net/sld
- 将
CssParameter
元素更改为SvgParameter
,保留属性 - 移除 xmlns:gml="http://www.opengis.net/gml"
- 将 ISO-8859-1 转换为 UTF-8
你的问题中有一些词被遗漏了,所以我没有完全理解所有的规则。在任何情况下,您都需要仔细检查 SLD 1.1 和 1.0 之间的差异,以确保您对这些差异制定了适当的规则。不要忘记,您可以通过不为输入文件未使用的差异编写规则来作弊。
这是一个简短的 Python 程序 (sld11-10.py
),它从输入中读取每个 XML 文件
目录,然后创建一个输出目录并写入一个相同的
相同目录中具有相同文件名的目录结构,
但内容已按照描述进行了转换。
#!/usr/bin/env python3
from lxml import etree
import os
import sys
sld10 = etree.XMLSchema(
etree.parse("http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd"))
sld11 = etree.XMLSchema(
etree.parse("http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd"))
transform = etree.XSLT(etree.parse("sld11-10.xsl"))
def walk(sour_dir: str, dest_dir: str) -> None:
os.mkdir(dest_dir)
for item in os.listdir(sour_dir):
sour_path = os.path.join(sour_dir, item)
dest_path = os.path.join(dest_dir, item)
if os.path.isdir(sour_path):
walk(sour_path, dest_path)
else:
sour_doc = etree.parse(sour_path)
if not sld11.validate(sour_doc):
print(sour_path, sld11.error_log.last_error)
dest_doc = transform(sour_doc)
if not sld10.validate(dest_doc):
print(dest_path, sld10.error_log.last_error)
dest_doc.write(dest_path,
pretty_print=True, xml_declaration=True, encoding="UTF-8")
return None
if __name__ == "__main__":
walk(sys.argv[1], sys.argv[2])
这里是引用的 XSLT 文件sld11-10.xsl
:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:se="http://www.opengis.net/se"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sld="http://www.opengis.net/sld"
exclude-result-prefixes="sld se">
<xsl:output encoding="UTF-8"/>
<!--
Chanage the version and the schemaLocation values
-->
<xsl:template match="/sld:StyledLayerDescriptor">
<StyledLayerDescriptor xmlns="http://www.opengis.net/sld"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:gml="http://www.opengis.net/gml">
<xsl:apply-templates select="@*"/>
<xsl:attribute name="version">1.0.0</xsl:attribute>
<xsl:attribute name="xsi:schemaLocation"
namespace="http://www.w3.org/2001/XMLSchema-instance">
<xsl:text>http://www.opengis.net/sld </xsl:text>
<xsl:text>http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd</xsl:text>
</xsl:attribute>
<xsl:apply-templates/>
</StyledLayerDescriptor>
</xsl:template>
<!--
Map SvgParameter elements in the http://www.opengis.net/se namespace
to CssParameter in the http://www.opengis.net/sld namespace
-->
<xsl:template match="se:SvgParameter">
<xsl:element name="CssParameter" namespace="http://www.opengis.net/sld">
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<!--
Map remaining http://www.opengis.net/se elements and attributes
to the http://www.opengis.net/sld namespace
-->
<xsl:template match="se:*">
<xsl:element name="{local-name()}" namespace="http://www.opengis.net/sld">
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<!--
Preserve all other elements and attributes
-->
<xsl:template match="*|@*">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<!--
Preserve processing instructuions and comments
-->
<xsl:template match="processing-instruction()|comment()">
<xsl:copy>.</xsl:copy>
</xsl:template>
</xsl:stylesheet>
if name == "main": walk(sys.argv[1], sys.argv[2]
部分的意思是
当您从命令行 运行 程序时,它将使用第一个
两个命令行参数作为 walk 例程的输入。例如,
假设您的 sld11-10.py
、sld11-10.xsl
和 input_directory
桌面,然后说input_directory
包含这样的文件
input_directory
file1.xml
file2.xml
subdirectory
file3.xml
然后,假设您没有名为 output_directory
的目录,您
可以运行这样的文件吗
sld11-10.py input_directory output_directory
该程序将创建具有以下结构的 output_direcory
:
output_directory
file1.xml
file2.xml
subdirectory
file3.xml
input_directory
和output_directory
的区别在于
output_directory
中的 XML 个文件将经过 XSLT 转换。
另外,请注意,在转换过程中,有关
XML 文件的有效性,SLD 1.0 和 SLD 1.1 都将被写入
过程中的屏幕。