如何转换 xml 中的无序元素以匹配 xsd:sequence 顺序? [英] How to transform unordered elements in xml to match an xsd:sequence order?

查看:22
本文介绍了如何转换 xml 中的无序元素以匹配 xsd:sequence 顺序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

相对于同名的回答情况子元素我正在尝试转换以下内容:

in contrast to the answered situation of equal named child elements I'm trying to convert the following:

<Person>
    <Address>5</Address>
    <Firstname>1234567890</Firstname>
    <Lastname>
        <MaidenName>The BFG</MaidenName>
        <StageName>GFB eht</StageName>
    </Lastname>
</Person>

进入想要的结果:

<Person>    
    <Firstname>1234567890</Firstname>
    <Lastname>
        <StageName>GFB eht</StageName>
        <MaidenName>The BFG</MaidenName>    
    </Lastname>
    <Address>5</Address>    
</Person>

但不断收到以下错误:
xml2xml.xsl 第 47 行 xsl:element 处的错误:XTDE0820:提供的元素名称是零长度字符串

But keep getting the following error:
Error at xsl:element on line 47 of xml2xml.xsl: XTDE0820: Supplied element name is a zero-length string

元素如何以正确的顺序传递和插入?

How can the elements passed and inserted in the correct order?

想要的结果符合提供的 XML 模式:

the wanted result is complying to the provided XML schema:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="Person" type="Person"/>
   <xs:complexType name="Person">
      <xs:sequence>
        <xs:element name="Firstname" type="xs:string"/>
        <xs:element name="Lastname" type="Lastname"/>
        <xs:element name="Address" type="xs:string"/>
      </xs:sequence>
   </xs:complexType>
  <xs:complexType name="Lastname">
    <xs:sequence>
        <xs:element name="StageName" type="xs:string"/>
        <xs:element name="MaidenName" type="xs:string"/>
    </xs:sequence>
   </xs:complexType>
</xs:schema>

我正在使用这个转换,我从 可以您将无序的 xml 转换为匹配 xsd:sequence 顺序?xsdsequence-order 并尝试适应:

I'm using this transformation, which I got from Can you transform unordered xml to match an xsd:sequence order? xsdsequence-order and tried to adapt:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kxsElemByName" match="xs:complexType" use="@name"/>

 <xsl:variable name="vSchema" select=
 "document('file:///D:/xslt/test/schema.xsd')"/> 

 <xsl:variable name="vDoc" select="/"/>

 <xsl:template match="/*">
  <xsl:variable name="vElem" select="."/>

  <xsl:for-each select="$vSchema">
   <xsl:apply-templates select=
     "key('kxsElemByName', name($vElem))">
    <xsl:with-param name="pElement" select="$vElem"/>
   </xsl:apply-templates>
  </xsl:for-each>
 </xsl:template>

 <xsl:template match="xs:complexType">
  <xsl:param name="pElement"/>

  <xsl:element name="{name($pElement)}">
       <xsl:apply-templates mode="generate"
            select="xs:sequence/*">
         <xsl:with-param name="pParent" select="$pElement"/>
       </xsl:apply-templates>
  </xsl:element>
 </xsl:template>

 <xsl:template match="xs:element" mode="generate">
      <xsl:param name="pParent"/>

      <xsl:variable name="vProp" select=
      "$pParent/*[local-name(.) = local-name(current())]/*"/>
      <xsl:element name="{local-name($vProp)}">
       <xsl:value-of select="$vProp"/>
   </xsl:element>
 </xsl:template>

</xsl:stylesheet>

推荐答案

假设您只是想根据 XSD 调整排序,请尝试下面的 XSLT.对于源 XML 中的每个元素,它会检查以在 XSD 中找到一个 xs:element,并检查该 xs:element 是否为复杂类型.如果是,则相应地对子元素进行排序.

Assuming you just wanted to adjust the ordering based on the XSD, try the XSLT below. For each element in the source XML, it checks to find an xs:element in the XSD, and for that xs:element whether is a complex type. If so, it then orders the child elements accordingly.

根据迈克尔的说法,这仍然非常脆弱.Kay 的回答,尽管它不再依赖于与元素名称匹配的复杂类型的名称.

This is still very fragile, as per Michael. Kay's answer, although it no longer relies on the name of the complex type matching the name of the element.

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output method="xml" indent="yes" />

    <xsl:key name="kxsElemByName" match="xs:element" use="@name"/>
    <xsl:key name="kxsTypeByName" match="xs:complexType" use="@name"/>

    <xsl:variable name="vSchema" select="document('file:///D:/xslt/test/schema.xsd')"/> 

    <xsl:template match="@*|node()" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*" priority="2">
        <xsl:variable name="current" select="." />
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:for-each select="$vSchema">
                <xsl:variable name="element" select="key('kxsElemByName', name($current))" />
                <xsl:variable name="complex" select="key('kxsTypeByName', $element/@type)" />
                <xsl:choose>
                <xsl:when test="$complex">
                    <xsl:for-each select="$complex/xs:sequence/xs:element">
                        <xsl:apply-templates select="$current/*[name() = current()/@name]" />
                    </xsl:for-each>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="$current/node()"/>
                </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

这篇关于如何转换 xml 中的无序元素以匹配 xsd:sequence 顺序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆