我正在尝试使用xslt处理一些旧数据文件,它们在对象描述语言(ODL)中包含一个大型文本元素,它具有类似XML的结构。我试图使用analyze-string将这些结构转换为xml。我可以匹配字符串并采取适当的措施,但我无法弄清楚如何翻译结构...
输入:
<?xml version="1.0" encoding="UTF-8"?>
<h4:HDF4map version="1.0.1"
xsi:schemaLocation="http://www.hdfgroup.org/HDF4/XML/schema/HDF4map/1.0.1/HDF4map.xsd"
xmlns:h4="http://www.hdfgroup.org/HDF4/XML/schema/HDF4map/1.0.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<h4:HDF4FileContents>
<h4:FileAttribute name="StructMetadata" origin="File Attribute: Arrays" combinesMultipleAttributes="true" id="ID_FA2">
<h4:stringValue>
GROUP=SwathStructure
GROUP=SWATH_1
SwathName="L2_Support_atmospheric&surface_product"
GROUP=Dimension
OBJECT=Dimension_1
DimensionName="GeoXTrack"
Size=30
END_OBJECT=Dimension_1
OBJECT=Dimension_2
DimensionName="GeoTrack"
Size=45
END_OBJECT=Dimension_2
END_GROUP=Dimension
GROUP=GeoField
OBJECT=GeoField_1
GeoFieldName="Latitude"
DataType=DFNT_FLOAT64
DimList=("GeoTrack","GeoXTrack")
END_OBJECT=GeoField_1
OBJECT=GeoField_2
GeoFieldName="Longitude"
DataType=DFNT_FLOAT64
DimList=("GeoTrack","GeoXTrack")
END_OBJECT=GeoField_2
OBJECT=GeoField_3
GeoFieldName="Time"
DataType=DFNT_FLOAT64
DimList=("GeoTrack","GeoXTrack")
END_OBJECT=GeoField_3
END_GROUP=GeoField
END_GROUP=SWATH_1
END_GROUP=SwathStructure
</h4:stringValue>
</h4:FileAttribute>
</h4:HDF4FileContents>
</h4:HDF4map>
我想将FileAttribute / stringValue转换为:
<root xmlns:h4="http://www.hdfgroup.org/HDF4/XML/schema/HDF4map/1.0.1">
<group name="SwathStructure">
<group name="SWATH_1">
<SwathName>"L2_Support_atmospheric&surface_product"</SwathName>
<group name="Dimension">
<Dimension_1>
<DimensionName>"GeoXTrack"</DimensionName>
<Size>30</Size>
</Dimension_1>
<Dimension_2>
<DimensionName>"GeoTrack"</DimensionName>
<Size>45</Size>
</Dimension_2>
</group>
<group name="GeoField">
<GeoField_1>
<GeoFieldName>"Latitude"</GeoFieldName>
<DataType>DFNT_FLOAT64</DataType>
<DimList>("GeoTrack","GeoXTrack")</DimList>
</GeoField_1>
<GeoField_2>
<GeoFieldName>"Longitude"</GeoFieldName>
<DataType>DFNT_FLOAT64</DataType>
<DimList>("GeoTrack","GeoXTrack")</DimList>
</GeoField_2>
<GeoField_3>
<GeoFieldName>"Time"</GeoFieldName>
<DataType>DFNT_FLOAT64</DataType>
<DimList>("GeoTrack","GeoXTrack")</DimList>
</GeoField_3>
</group>
</group>
</group>
</root>
这是我到目前为止所做的:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:h4="http://www.hdfgroup.org/HDF4/XML/schema/HDF4map/1.0.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xlink="http://www.w3.org/1999/xlink" exclude-result-prefixes="xsi xlink">
<!-- Parameters to identify files to process -->
<xsl:param name="recordSetPath"/>
<xsl:param name="fileNamePattern"/>
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:element name="root">
<xsl:namespace name="h4" select="'http://www.hdfgroup.org/HDF4/XML/schema/HDF4map/1.0.1'"/>
<xsl:variable name="xmlFilesSelect" select="concat($recordSetPath, '?select=',$fileNamePattern)"/>
<xsl:for-each select="collection(iri-to-uri($xmlFilesSelect))">
<xsl:apply-templates/>
</xsl:for-each>
</xsl:element>
</xsl:template>
<xsl:template match="h4:FileAttribute[@name='StructMetadata']">
<xsl:variable name="elementValue" select="h4:stringValue"/>
<xsl:analyze-string select="$elementValue" regex="(.*)=(.*)">
<xsl:matching-substring>
<xsl:variable name="objectName" select="normalize-space(regex-group(1))"/>
<xsl:variable name="objectValue" select="normalize-space(regex-group(2))"/>
<xsl:choose>
<xsl:when test="$objectName='GROUP'">
<xsl:element name="group">
<xsl:attribute name="name" select="$objectValue"/>
</xsl:element>
</xsl:when>
<xsl:when test="contains($objectName,'END-GROUP')">
<xsl:value-of select="'</group>'"/>
</xsl:when>
<xsl:when test="$objectName='OBJECT'">
<xsl:element name="{$objectValue}"/>
</xsl:when>
<xsl:when test="contains($objectName,'END-OBJECT')">
<xsl:value-of select="'</group>'"/>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{$objectName}">
<xsl:value-of select="$objectValue"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
答案 0 :(得分:1)
这还不是一个完整的解决方案。但我首先要从您的输入中创建简单的XML。然后处理新的XML树。这应该可以使用apply-templates,尽管您可能需要使用pull处理方法而不是push(即,实际上可能不适用于apply-templates ...)。
这些模板构成了一个简单的数据XML,使每个行的等号前面的元素名称和元素的文本节点之后的东西。
<xsl:template match="h4:stringValue">
<xsl:variable name="newRoot">
<xsl:for-each select="tokenize(.,'
')">
<xsl:variable name="newElementName" select="substring-before(.,'=')"/>
<xsl:if test="$test ne '' and $test ne ' '" >
<xsl:element name="{$newElementName}">
<xsl:value-of select="substring-after(.,'=')"/>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:sequence select="$newRoot"/>
<xsl:apply-templates select="$newRoot" mode="process"/>
</xsl:template>
<xsl:template match="text()"/>
答案 1 :(得分:1)
数据需要超级一致才能实现,但我要做的是创建一个中间XML结构(如user5923提出的那样),然后对其进行处理。
此解决方案使用了大量disable-output-escaping
,并且很容易导致输出格式不正确。它适用于此示例,但如果您使用永久解决方案,请谨慎使用。
XML输入
<h4:HDF4map version="1.0.1"
xsi:schemaLocation="http://www.hdfgroup.org/HDF4/XML/schema/HDF4map/1.0.1/HDF4map.xsd"
xmlns:h4="http://www.hdfgroup.org/HDF4/XML/schema/HDF4map/1.0.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<h4:HDF4FileContents>
<h4:FileAttribute name="StructMetadata" origin="File Attribute: Arrays" combinesMultipleAttributes="true" id="ID_FA2">
<h4:stringValue>
GROUP=SwathStructure
GROUP=SWATH_1
SwathName="L2_Support_atmospheric&surface_product"
GROUP=Dimension
OBJECT=Dimension_1
DimensionName="GeoXTrack"
Size=30
END_OBJECT=Dimension_1
OBJECT=Dimension_2
DimensionName="GeoTrack"
Size=45
END_OBJECT=Dimension_2
END_GROUP=Dimension
GROUP=GeoField
OBJECT=GeoField_1
GeoFieldName="Latitude"
DataType=DFNT_FLOAT64
DimList=("GeoTrack","GeoXTrack")
END_OBJECT=GeoField_1
OBJECT=GeoField_2
GeoFieldName="Longitude"
DataType=DFNT_FLOAT64
DimList=("GeoTrack","GeoXTrack")
END_OBJECT=GeoField_2
OBJECT=GeoField_3
GeoFieldName="Time"
DataType=DFNT_FLOAT64
DimList=("GeoTrack","GeoXTrack")
END_OBJECT=GeoField_3
END_GROUP=GeoField
END_GROUP=SWATH_1
END_GROUP=SwathStructure
</h4:stringValue>
</h4:FileAttribute>
</h4:HDF4FileContents>
</h4:HDF4map>
XSLT 2.0
<xsl:stylesheet version="2.0" xmlns:h4="http://www.hdfgroup.org/HDF4/XML/schema/HDF4map/1.0.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/h4:HDF4map/h4:HDF4FileContents/h4:FileAttribute[@name='StructMetadata']/h4:stringValue">
<xsl:variable name="pass1">
<xsl:analyze-string select="." regex="([^=\s]+)=([^=\s]+)">
<xsl:matching-substring>
<tag name="{regex-group(1)}" value="{regex-group(2)}"/>
</xsl:matching-substring>
<xsl:non-matching-substring/>
</xsl:analyze-string>
</xsl:variable>
<root>
<xsl:for-each select="$pass1/tag">
<xsl:choose>
<xsl:when test="@name='END_OBJECT'">
<xsl:value-of select="concat('</',@value,'>
')" disable-output-escaping="yes"/>
</xsl:when>
<xsl:when test="starts-with(@name,'END_')">
<xsl:value-of select="concat('</',lower-case(substring-after(@name,'END_')),'>
')" disable-output-escaping="yes"/>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="@name='OBJECT'">
<xsl:value-of select="concat('<',@value,'>
')" disable-output-escaping="yes"/>
</xsl:when>
<xsl:when test="following-sibling::*[@name=concat('END_',current()/@name)]">
<xsl:value-of select="concat('<',lower-case(@name),' name="')" disable-output-escaping="yes"/>
<xsl:value-of select="replace(@value,'^"|"$','')"/>
<xsl:value-of select="'">
'" disable-output-escaping="yes"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat('<',@name,'>')" disable-output-escaping="yes"/>
<xsl:value-of select="@value"/>
<xsl:value-of select="concat('</',@name,'>
')" disable-output-escaping="yes"/>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
XML输出(我对输出进行了格式化以便于阅读。有一些

用于输出中断以帮助格式化,但这些可以删除。)
<root xmlns:h4="http://www.hdfgroup.org/HDF4/XML/schema/HDF4map/1.0.1">
<group name="SwathStructure">
<group name="SWATH_1">
<SwathName>"L2_Support_atmospheric&surface_product"</SwathName>
<group name="Dimension">
<Dimension_1>
<DimensionName>"GeoXTrack"</DimensionName>
<Size>30</Size>
</Dimension_1>
<Dimension_2>
<DimensionName>"GeoTrack"</DimensionName>
<Size>45</Size>
</Dimension_2>
</group>
<group name="GeoField">
<GeoField_1>
<GeoFieldName>"Latitude"</GeoFieldName>
<DataType>DFNT_FLOAT64</DataType>
<DimList>("GeoTrack","GeoXTrack")</DimList>
</GeoField_1>
<GeoField_2>
<GeoFieldName>"Longitude"</GeoFieldName>
<DataType>DFNT_FLOAT64</DataType>
<DimList>("GeoTrack","GeoXTrack")</DimList>
</GeoField_2>
<GeoField_3>
<GeoFieldName>"Time"</GeoFieldName>
<DataType>DFNT_FLOAT64</DataType>
<DimList>("GeoTrack","GeoXTrack")</DimList>
</GeoField_3>
</group>
</group>
</group>
</root>