如何使用XSLT1.0为非继承XML文件添加结构



我有一些具有伪结构的非继承xml。每个对象都声明一个父对象("根"对象除外)和零个或多个子对象,但使用id和引用属性而不是嵌套结构。我想将其转换为嵌套结构。

<document>
    <object id="6" children="12,15"/>
    <object id="12" parent="6" children="13,18"/>
    <object id="13" parent="12" children="14,16,17"/>
    <object id="14" parent="13"/>
    <object id="15" parent="6" children="21,22"/>
    <object id="16" parent="13"/>
    <object id="17" parent="13"/>
    <object id="18" parent="12" children="23,25"/>
    <object id="19" parent="23"/>
    <object id="21" parent="15"/>
    <object id="22" parent="15"/>
    <object id="23" parent="18" children="19,24"/>
    <object id="24" parent="23"/>
    <object id="25" parent="18"/>
</document>

对于记录,实际文档还包含对象定义,对象也在属性中引用这些对象定义,类似于类,但我需要通过引用id从定义中检索元素名称。在这个过程中的某个时刻,我将每个"对象"的名称转换为"模板"或"小节"。如果它简化了事情,我可以在应用该结构后执行此操作。我还为children属性提供了一个标记化的"函数",因为我使用的是XSLT1.0,它没有内置它。

所以对于上面的例子,我想要这个输出:

<document>
    <object id="6">
        <object id="12">
            <object id="13">
                <object id="14"/>
                <object id="16"/>
                <object id="17"/>
            </object>
            <object id="18">
                <object id="23">
                    <object id="19"/>
                    <object id="24"/>
                </object>
                <object id="25"/>
            </object>
        </object>
        <object id="15">
            <object id="21"/>
            <object id="22"/>
        </object>
    </object>
</document>

请记住,这些对象元素包含其他信息、属性、数据等。为了简化示例,这些元素已被删除,但可能会给问题增加一层复杂性。

如果可能的话,我想以一种优雅和可扩展的方式来做这件事。我不是被迫的,而是更喜欢使用XSL1.0(这样它就可以与现有的服务器软件集成)。

衷心感谢任何能帮助我或为我指明正确方向的人!

如果不执行完整的XSLT,您可以像下面这样构建转换:基本上,Books的模板将调用章节的应用模板,章节的模板将应用主题的模板,等等。这里的关键是将父级的id放入一个变量中,这样您就可以在随后的应用模板调用中使用它来查找子级。

<document>
   <xsl:apply-templates select="/document/book" />
</document>
<xsl:template match="/document/book">
   <xsl:variable name="bookid">
      <xsl:value-of select="@id"/>
   </xsl:variable>
   <xsl:element name="book">
      <xsl:attribute name="id">
         <xsl:value-of select="@id"/>
      </xsl:attribute>
      <xsl:apply-templates select="/document/chapter[@parent=$bookid]" />
   </xsl:element>
</xsl:template>
<xsl:template match="/document/chapter">
   Template for chapter would be replicated from the book template above
   .
   .
   .
</xsl:template>

这个简短而简单的完整转换

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:key name="kChildren" match="object" use="@parent"/>
 <xsl:template match="/*">
   <document>
     <xsl:apply-templates select="*[not(@parent)]"/>
   </document>
 </xsl:template>
 <xsl:template match="object">
  <object id="{@id}">
    <xsl:apply-templates select="key('kChildren', @id)"/>
  </object>
 </xsl:template>
</xsl:stylesheet>

应用于所提供的XML文档时

<document>
    <object id="6" children="12,15"/>
    <object id="12" parent="6" children="13,18"/>
    <object id="13" parent="12" children="14,16,17"/>
    <object id="14" parent="13"/>
    <object id="15" parent="6" children="21,22"/>
    <object id="16" parent="13"/>
    <object id="17" parent="13"/>
    <object id="18" parent="12" children="23,25"/>
    <object id="19" parent="23"/>
    <object id="21" parent="15"/>
    <object id="22" parent="15"/>
    <object id="23" parent="18" children="19,24"/>
    <object id="24" parent="23"/>
    <object id="25" parent="18"/>
</document>

生成所需的正确结果

<document>
    <object id="6">
        <object id="12">
            <object id="13">
                <object id="14"/>
                <object id="16"/>
                <object id="17"/>
            </object>
            <object id="18">
                <object id="23">
                    <object id="19"/>
                    <object id="24"/>
                </object>
                <object id="25"/>
            </object>
        </object>
        <object id="15">
            <object id="21"/>
            <object id="22"/>
        </object>
    </object>
</document>

说明:正确使用钥匙。

相关内容

  • 没有找到相关文章

最新更新