使用 XSLT 或 XQuery 脚本重构重新嵌套元素
Refactoring Re-nesting elements with XSLT or XQuery Scripts
我目前正在重构 XML 批文档,该过程涉及将 xml 重构为新修订的 DTD 模式。作为使用新 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>
*note that <qty>
has moved
*note <partno>
has moved
*note <nsn>
not includes children elements with the contents sorted
此外,某些实例包含一个 <uoc>
元素作为子元素嵌套在 <desc>
中。
<desc>
bolt 1/2inch
<uoc>XYZ</uoc>
</desc>
其中 <uoc>
实际上应该在 <callout>
之后和
之前
<qty>
非常感谢任何有关 XSLT 样式表或 XQuery 脚本的帮助,以及为什么选择一种语言而不是另一种语言的简短解释。我目前正在使用 Oxygen 17 XML 编辑器
当大部分输出与输入相同时,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 批文档,该过程涉及将 xml 重构为新修订的 DTD 模式。作为使用新 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>
*note that
<qty>
has moved *note<partno>
has moved *note<nsn>
not includes children elements with the contents sorted
此外,某些实例包含一个 <uoc>
元素作为子元素嵌套在 <desc>
中。
<desc>
bolt 1/2inch
<uoc>XYZ</uoc>
</desc>
其中 <uoc>
实际上应该在 <callout>
之后和
<qty>
非常感谢任何有关 XSLT 样式表或 XQuery 脚本的帮助,以及为什么选择一种语言而不是另一种语言的简短解释。我目前正在使用 Oxygen 17 XML 编辑器
当大部分输出与输入相同时,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>