我有一个 xml 文档,如下所示:
<document>
<primitive name="password" type="xs:string" path="" mandatory="false" />
<structure name="username" mandatory="true">
<primitive name="first-name" type="xs:string" path="" mandatory="true" />
<primitive name="last-name" type="xs:string" path="" mandatory="true" />
</structure>
<list name="addresses" path="" mandatory="true">
<structure name="address" mandatory="true">
<primitive name="country" type="xs:string" path="" mandatory="true" default-value="HU"/>
<primitive name="po-box" type="xs:string" path="" mandatory="true" />
</structure>
</list>
<list name="owned-phones" path="" mandatory="true">
<structure name="phone" mandatory="true">
<primitive name="number" type="xs:int" path="" mandatory="true" />
<primitive name="device-name" type="xs:string" path="" mandatory="true" />
<list name="similar-devices" path="" mandatory="true">
<structure name="device" mandatory="true">
<primitive name="device-name" type="xs:string" path="" mandatory="true" />
</structure>
</list>
</structure>
</list>
<list name="aliases" path="" mandatory="true">
<primitive name="alias" type="xs:string" path="" mandatory="true" />
</list>
<template name="tou">
<![CDATA[
wombat
]]>
</template>
这描述了数据结构的规则,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<document>
<password>ajshakjsdh</password>
<username>
<first-name>Kevin</first-name>
<last-name>Smith</last-name>
</username>
<addresses>
<address>
<country>HU</country>
<po-box>12234</po-box>
</address>
<address>
<country>US</country>
<po-box>666</po-box>
</address>
</addresses>
<owned-phones>
<phone>
<number>2431241</number>
<device-name>Nokia</device-name>
<similar-devices>
<device>
<device-name>Windozfon</device-name>
</device>
</similar-devices>
</phone>
<phone>
<number>68741</number>
<device-name>Samsung</device-name>
<similar-devices>
<device>
<device-name>Android</device-name>
</device>
<device>
<device-name>Blackberry</device-name>
</device>
</similar-devices>
</phone>
</owned-phones>
<aliases>
<alias>Alias1</alias>
<alias>Alias2</alias>
</aliases>
<!-- tou is missing but not mandatory -->
</document>
我有一组转换规则,可用于将第一个 xml 文件转换为 xsd 文档,该文档可用于验证数据结构(第二个代码)块):
<primitive name="$primitive_name" type="$primitive_type" mandatory="$primitive_mandatory" />
转换为
<xs:element name="$primitive_name" type="$primitive_type" minOccurs="$primitive_mandatory ? 1 : 0" maxOccurs="1" />
<structure name="$structure_name" mandatory="$structure_mandatory">
<!-- anything inside recursively transformed -->
</structure>
转换为
<xs:element name="$structure_name" minOccurs="$structure_mandatory ? 1 : 0" maxOccurs="1">
<xs:complexType>
<xs:all>
<!-- anything inside recursively transformed -->
</xs:all>
</xs:complexType>
</xs:element>
<list name="$list_name" mandatory="$list_mandatory">
<!-- anything inside recursively transformed -->
</list>
转换为
<xs:element name="$list_name" minOccurs="$list_mandatory ? 1 : 0">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<!-- anything inside recursively transformed -->
</xs:sequence>
</xs:complexType>
</xs:element>
我的问题是我应该使用什么工具进行这些简单的转换?我听说 XSLT 是这里的方法。我做了一些关于它的研究,这对我来说似乎有些过分。至少我无法在 XSLT 中找到正确的转换规则。你能提供一些指示我应该从哪里开始吗?
答案 0 :(得分:3)
XSLT非常适合您的问题。您可以轻松地将结构映射到将以递归方式调用的各个模板。
以下是 XSLT 2.0 样式表的示例,其中包含仅提供您提供的示例的模板。它应该提供一个良好的起点。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="document">
<xs:schema elementFormDefault="qualified">
<xsl:apply-templates/>
</xs:schema>
</xsl:template>
<xsl:template match="primitive">
<xs:element name="{@name}" type="{@type}" minOccurs="{if(@mandatory eq 'true') then 1 else 0}" maxOccurs="1" />
</xsl:template>
<xsl:template match="structure">
<xs:element name="{@name}" minOccurs="{if(@mandatory eq 'true') then 1 else 0}" maxOccurs="1">
<xs:complexType>
<xs:all>
<xsl:apply-templates/>
</xs:all>
</xs:complexType>
</xs:element>
</xsl:template>
<xsl:template match="list">
<xs:element name="{@name}" minOccurs="{if(@mandatory eq 'true') then 1 else 0}">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xsl:apply-templates/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xsl:template>
</xsl:stylesheet>
有很多方法可以达到相同的效果。寻找一个有效使用XSLT模板的优秀XSLT教程。避免使用for-each
专注于单模板解决方案的那些。您可以使用模板实现所需的一切(不使用<xsl:for-each>
,这将使其变得更加复杂)。
如果您的支持仅限于 XSLT 1.0 ,您将无法在minOccurs
属性中使用(XPath 2.0)代码,但您可以生成属性嵌套<xsl:attribute>
并使用<xsl:choose>
来计算其内容。
上面的样式表可以在XSLT 1.0中重写,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="document">
<xs:schema elementFormDefault="qualified">
<xsl:apply-templates/>
</xs:schema>
</xsl:template>
<xsl:template match="primitive">
<xs:element name="{@name}" type="{@type}" maxOccurs="1">
<xsl:attribute name="minOccurs">
<xsl:choose>
<xsl:when test="@mandatory = 'true'">1</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xs:element>
</xsl:template>
<xsl:template match="structure">
<xs:element name="{@name}" maxOccurs="1">
<xsl:attribute name="minOccurs">
<xsl:choose>
<xsl:when test="@mandatory = 'true'">1</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xs:complexType>
<xs:all>
<xsl:apply-templates/>
</xs:all>
</xs:complexType>
</xs:element>
</xsl:template>
<xsl:template match="list">
<xs:element name="{@name}">
<xsl:attribute name="minOccurs">
<xsl:choose>
<xsl:when test="@mandatory = 'true'">1</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xsl:apply-templates/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
你是对的,XSLT是可以使用的工具。
对于你的情况,创建你的xsl文件应该非常快,因为你不需要转换很多语句。
您将需要XSL和XPATH(Xml查询语言)来完成工作
首先,我建议去http://www.w3schools.com/xsl/ 你会在那里找到XSLT的参考文档:http://www.w3.org/TR/xslt
对于XPATH:http://www.w3.org/TR/xpath/和http://www.w3schools.com/XPath/
希望它会有所帮助。 享受;)
晏