您可以转换无序的 xml 以匹配 xsd:sequence 顺序吗?

发布于 2024-12-10 06:28:46 字数 788 浏览 0 评论 0原文

您好,我需要使用 xslt 将无序 xml 转换为 xsd 模式中指定的正确顺序,

<Person>
    <property name="address" value="5" />
    <property name="firstname" value="1234567890" />
    <property name="lastname" value="The BFG" />
</Person>

需要使用

<xs:element name="Person">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="firstname" type="xs:string"/>
            <xs:element name="lastname" type="xs:string"/>
            <xs:element name="address" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

xml 可以具有任何顺序的属性,其中包含 10 多个属性元素。我尝试使用 xsl: for-each 尝试处理 xml,但我对如何让 xslt 将 xml 转换为序列定义的正确顺序感到困惑,

任何帮助将不胜感激

Hi i need to transform unorderd xml using xslt to the correct order as specified in an xsd schema

<Person>
    <property name="address" value="5" />
    <property name="firstname" value="1234567890" />
    <property name="lastname" value="The BFG" />
</Person>

would need to be transformed using

<xs:element name="Person">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="firstname" type="xs:string"/>
            <xs:element name="lastname" type="xs:string"/>
            <xs:element name="address" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

The xml could have the properties in any order, with upwars of 10+ property elements.I have tried using an xsl:for-each to try and process the xml but i'm stumped at how to get the xslt to transform the xml into the correct order as defined by the sequence

any help would be appreciated

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

◇流星雨 2024-12-17 06:28:46

这可能不是最好的方法,但似乎效果不错。我不确定 xs:element 的处理顺序是否得到保证。另外,这是在 oXygen 中使用 Saxon-HE 9.3.0.5 测试的 XSLT 2.0 答案。

XML 输入(修改了 Person 的大小写以匹配架构):

<person>
  <property name="address" value="5" />
  <property name="firstname" value="1234567890" />
  <property name="lastname" value="The BFG" />
</person>

外部 XSD 架构文件 (schema.xsd):

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="person">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="firstname" type="xs:string"/>
        <xs:element name="lastname" type="xs:string"/>
        <xs:element name="address" type="xs:string"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

XSLT 2.0 样式表:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:variable name="input">
    <xsl:copy-of select="/"/>
  </xsl:variable>

  <xsl:template match="/*">
    <xsl:variable name="firstContext" select="name()"/>
    <xsl:variable name="xsdElems" select="document('schema.xsd')/xs:schema/xs:element[@name=$firstContext]/xs:complexType/xs:sequence/xs:element/@name"/>
    <xsl:element name="{$firstContext}">
      <xsl:for-each select="$xsdElems">
        <xsl:variable name="secondContext" select="."/>
        <xsl:element name="{$secondContext}">
          <xsl:value-of select="$input/*/*[@name=$secondContext]/@value"/>
        </xsl:element>
      </xsl:for-each>      
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

XML 输出:

<person>
   <firstname>1234567890</firstname>
   <lastname>The BFG</lastname>
   <address>5</address>
</person>

希望这会有所帮助。

This may not be the best way, but it seems to work ok. I'm not sure if the order that the xs:element's are processed is guaranteed though. Also, this is an XSLT 2.0 answer tested with Saxon-HE 9.3.0.5 in oXygen.

XML Input (modified the case of Person to match the schema):

<person>
  <property name="address" value="5" />
  <property name="firstname" value="1234567890" />
  <property name="lastname" value="The BFG" />
</person>

External XSD Schema file (schema.xsd):

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="person">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="firstname" type="xs:string"/>
        <xs:element name="lastname" type="xs:string"/>
        <xs:element name="address" type="xs:string"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

XSLT 2.0 Stylesheet:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:variable name="input">
    <xsl:copy-of select="/"/>
  </xsl:variable>

  <xsl:template match="/*">
    <xsl:variable name="firstContext" select="name()"/>
    <xsl:variable name="xsdElems" select="document('schema.xsd')/xs:schema/xs:element[@name=$firstContext]/xs:complexType/xs:sequence/xs:element/@name"/>
    <xsl:element name="{$firstContext}">
      <xsl:for-each select="$xsdElems">
        <xsl:variable name="secondContext" select="."/>
        <xsl:element name="{$secondContext}">
          <xsl:value-of select="$input/*/*[@name=$secondContext]/@value"/>
        </xsl:element>
      </xsl:for-each>      
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

XML Output:

<person>
   <firstname>1234567890</firstname>
   <lastname>The BFG</lastname>
   <address>5</address>
</person>

Hope this helps.

寻找一个思念的角度 2024-12-17 06:28:46

这是一个 XSLT 1.0 解决方案

<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:element" use="@name"/>

 <xsl:variable name="vSchema" select=
  "document('file:///c:/temp/delete/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:element">
  <xsl:param name="pElement"/>

  <xsl:element name="{name($pElement)}">
   <xsl:apply-templates mode="generate"
        select="xs:complexType/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/property[@name = current()/@name]"/>

  <xsl:element name="{$vProp/@name}">
   <xsl:value-of select="$vProp/@value"/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时Person 重命名为 person匹配架构):

<person>
    <property name="address" value="5" />
    <property name="firstname" value="1234567890" />
    <property name="lastname" value="The BFG" />
</person>

如果提供的 XML 架构位于文件 c:\temp\delete\schema.xsd:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="person">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="firstname" type="xs:string"/>
        <xs:element name="lastname" type="xs:string"/>
        <xs:element name="address" type="xs:string"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

则需要正确的结果产生

<person>
   <firstname>1234567890</firstname>
   <lastname>The BFG</lastname>
   <address>5</address>
</person>

Here is an XSLT 1.0 solution:

<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:element" use="@name"/>

 <xsl:variable name="vSchema" select=
  "document('file:///c:/temp/delete/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:element">
  <xsl:param name="pElement"/>

  <xsl:element name="{name($pElement)}">
   <xsl:apply-templates mode="generate"
        select="xs:complexType/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/property[@name = current()/@name]"/>

  <xsl:element name="{$vProp/@name}">
   <xsl:value-of select="$vProp/@value"/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the provided XML document (Person renamed to person to match the schema):

<person>
    <property name="address" value="5" />
    <property name="firstname" value="1234567890" />
    <property name="lastname" value="The BFG" />
</person>

and if the provided XML schema is in the file c:\temp\delete\schema.xsd:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="person">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="firstname" type="xs:string"/>
        <xs:element name="lastname" type="xs:string"/>
        <xs:element name="address" type="xs:string"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

then the wanted, correct result is produced:

<person>
   <firstname>1234567890</firstname>
   <lastname>The BFG</lastname>
   <address>5</address>
</person>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文