【问题标题】:Refactoring Re-nesting elements with XSLT or XQuery Scripts使用 XSLT 或 XQuery 脚本重构重新嵌套元素
【发布时间】:2016-08-17 17:21:49
【问题描述】:

我目前正在重构一批 XML 文档,该过程涉及将 xml 重构为新修订的 DTD Schema。由于使用了新的 DTD,许多最初使用的元素要么被重新利用、重新嵌套在其他元素中,要么被完全删除。 下面的示例是针对 DTD 进行验证时的无效 xml 文档。为了加快重构 XML 的过程,我认为 XQuery 脚本或 XSLT 转换可能会有所帮助。但是,我对这两种方法的经验都为零,而且对 XML 还是很陌生。有人可以向我解释一下 XQuery、XSLT 还是 Xpath 中哪种语言在重构这些文档时最相关。

无效的 XML:

<PartsDoc foo=”” baa=”” bar=”” revno=”” docno=”” > 
    <PartsDocInfo>
        <repairlvl level=”shop” /> 
        <title id=”123”> Foo Electrical Control Box </title> 
    </PartsDocInfo> 

    <Parts.Category> 

    <figure id=”123” >
        <title id=”123”> Control Box Panels </title> 

    <subfig id=”123”>
            <graphic img=”foo.jpg” /> 
        </subfig>
    <!- - everything above is valid, the below portion is not - ->



<parts.item> 
            <callout id=”123”  config=”123” label=”1” /> 
            <mrs service=”shop” sc=”” mc=”” rec=”” /> 
            <nsn niin=”00-123-4567”> 4444-00-123-5467</nsn> 
            <cageno>12345</cageno>
            <partno>12345</partno>
            <name/>
            <desc id=”123” > Bolt 1/2inch </desc>
            <qty>4</qty>
 <parts.item>   
    </parts.category> 

期望的输出:

<PartsDoc foo=”” baa=”” bar=”” revno=”” docno=”” > 

        <PartsDocInfo>
        <repairlvl level=”shop” /> 
        <title id=”123”> Foo Electrical Control Box </title> 
    </PartsDocInfo> 
<Parts.Category> 
    <figure id=”123” >
        <title id=”123”> Control Box Panels </title> 
<subfig id=”123”>
          <graphic img=”foo.jpg” />
</subfig>
    <parts.item> 
        <callout id=”123”  config=”123” label=”1” /> 
<qty>4</qty>
<mrs service=”shop” sc=”” mc=”” rec=”” /> 
<nsn>
        <fsc>4444</fsc>
        <niin>00-12-5467
</nsn>
        <partno>12345</partno>
        <cageno>12345</cageno>
        <name/>
        <desc id=”123” > Bolt 1/2inch </desc>
    <parts.item>    
</parts.category> 

*注意&lt;qty&gt; 已移动 *注意&lt;partno&gt; 已移动 *注意&lt;nsn&gt; 不包括内容已排序的子元素

此外,某些实例包含一个 &lt;uoc&gt; 元素,该元素作为子元素嵌套在 &lt;desc&gt; 中。

<desc> 
    bolt 1/2inch
        <uoc>XYZ</uoc>
</desc>

&lt;uoc&gt; 实际上应该在 &lt;callout&gt; 之后和之前

<qty>

非常感谢任何有关 XSLT 样式表或 XQuery 脚本的帮助,并简要说明为什么选择一种语言而不是另一种语言。我目前正在使用 Oxygen 17 XML 编辑器

【问题讨论】:

    标签: xml xpath xquery oxygenxml


    【解决方案1】:

    当输出的大部分内容与输入相同时,XSLT 通常更符合要求。总的原则是编写一个样式表,其中包含递归复制元素的一般规则,然后为想要做不同事情的元素添加规则。

    在 XSLT 3.0 中,通用规则是:

    <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      version="3.0">
      <xsl:mode on-no-match="shallow-copy"/>
    
      ... other code goes here ...
    </xsl:transform>
    

    虽然在早期版本中是:

    <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      version="2.0">
    
      <xsl:template match="*">
       <xsl:copy>
        <xsl:copy-of select="@*">
        <xsl:apply-templates/>
       </xsl:copy>
      </xsl:template>
    
      ... other code goes here ...
    </xsl:transform>
    

    您可以编写对parts.item 重新排序的模板规则:

    <xsl:template match="parts.item">
      <parts.item>
        <xsl:copy-of select="callout"/>
        <xsl:copy-of select="qty"/>
        <xsl:copy-of select="mrs"/>
        <nsn>
          <fsc><xsl:value-of select="substring-before(nsn, '-')"/></fsc>
          <niin><xsl:value-of select="nsn/@niin"/></niin>
        </nsn>
        <xsl:copy-of select="partno"/>
        <xsl:copy-of select="cageno"/>
        <xsl:copy-of select="name"/>
        <xsl:copy-of select="desc"/>
     </parts.item>
    

    把这些放在一起,下面的 XSLT 2.0 样式表:

    <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="2.0">
    
        <xsl:strip-space elements="*"/>
        <xsl:output indent="yes"/>
    
        <xsl:template match="*">
            <xsl:copy>
                <xsl:copy-of select="@*"/>
                <xsl:apply-templates/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="parts.item">
            <parts.item>
                <xsl:copy-of select="callout"/>
                <xsl:copy-of select="qty"/>
                <xsl:copy-of select="mrs"/>
                <nsn>
                    <fsc><xsl:value-of select="substring-before(nsn, '-')"/></fsc>
                    <niin><xsl:value-of select="nsn/@niin"/></niin>
                </nsn>
                <xsl:copy-of select="partno"/>
                <xsl:copy-of select="cageno"/>
                <xsl:copy-of select="name"/>
                <xsl:copy-of select="desc"/>
            </parts.item>
        </xsl:template>
    </xsl:transform>
    

    应用于以下源文档:

    <PartsDoc foo="" baa="" bar="" revno="" docno="" > 
        <PartsDocInfo>
            <repairlvl level="shop" /> 
            <title id="123"> Foo Electrical Control Box </title> 
        </PartsDocInfo> 
    
        <Parts.Category> 
    
            <figure id="123" >
            <title id="123"> Control Box Panels </title> 
    
             <subfig id="123">
                        <graphic img="foo.jpg" /> 
             </subfig>
                    <!-- everything above is valid, the below portion is not -->
    
                    <parts.item> 
                        <callout id="123"  config="123" label="1" /> 
                        <mrs service="shop" sc="" mc="" rec="" /> 
                        <nsn niin="00-123-4567"> 4444-00-123-5467</nsn> 
                        <cageno>12345</cageno>
                        <partno>12345</partno>
                        <name/>
                        <desc id="123" > Bolt 1/2inch </desc>
                        <qty>4</qty>
                    </parts.item>
            </figure>
        </Parts.Category>
    </PartsDoc>
    

    产生以下输出:

    <?xml version="1.0" encoding="UTF-8"?>
    <PartsDoc foo="" baa="" bar="" revno="" docno="">
       <PartsDocInfo>
          <repairlvl level="shop"/>
          <title id="123"> Foo Electrical Control Box </title>
       </PartsDocInfo>
       <Parts.Category>
          <figure id="123">
             <title id="123"> Control Box Panels </title>
             <subfig id="123">
                <graphic img="foo.jpg"/>
             </subfig>
             <parts.item>
                <callout id="123" config="123" label="1"/>
                <qty>4</qty>
                <mrs service="shop" sc="" mc="" rec=""/>
                <nsn>
                   <fsc> 4444</fsc>
                   <niin>00-123-4567</niin>
                </nsn>
                <partno>12345</partno>
                <cageno>12345</cageno>
                <name/>
                <desc id="123"> Bolt 1/2inch </desc>
             </parts.item>
          </figure>
       </Parts.Category>
    </PartsDoc>
    

    【讨论】:

    • 那你做错了。在您提供的 XML 和我的 XSLT 中有一些琐碎的拼写错误,但在修复这些错误后,它按预期工作,我添加了完整的细节。
    • Michael 如果我想在parts.item 元素中保留任何属性,我该怎么做?
    • 请不要以评论的形式提出补充问题。 SO 问题/答案格式不是为此而设计的。如果您有补充问题,请将其作为一个新问题提出,并从第一原则进行解释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 2011-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多