首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将xml转换为另一个xml的最简单方法是什么?

将xml转换为另一个xml的最简单方法是什么?
EN

Stack Overflow用户
提问于 2014-05-12 14:53:29
回答 2查看 96关注 0票数 1

我有一个xml文档,如下所示:

代码语言:javascript
复制
<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>

这描述了数据结构的规则,如下所示:

代码语言:javascript
复制
<?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文档,该文档可用于验证数据结构(第二个代码块):

代码语言:javascript
复制
<primitive name="$primitive_name" type="$primitive_type" mandatory="$primitive_mandatory" />

转换为

代码语言:javascript
复制
<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>

转换为

代码语言:javascript
复制
<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>

转换为

代码语言:javascript
复制
<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中找到正确的转换规则。你能给我一些建议吗?我该从哪里开始?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-05-12 15:43:59

XSLT是解决问题的很好的解决方案。您可以很容易地将您的结构映射到各个模板,这些模板将被递归调用。

下面是一个XSLT2.0样式表的示例,其中包含您提供的示例的模板。这应该是一个很好的起点。

代码语言:javascript
复制
<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>,这会使它变得过于复杂)。

如果您的支持仅限于XSLT1.0,则无法在minOccurs属性中使用(XPath 2.0)代码,但可以使用嵌套<xsl:attribute>生成属性并使用<xsl:choose>计算其内容。

上面的样式表可以在XSLT1.0中重写,如下所示:

代码语言:javascript
复制
<?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>
票数 3
EN

Stack Overflow用户

发布于 2014-05-12 15:37:52

您说得对,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/

希望能帮上忙。享受;)

延恩

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23612315

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档