【问题标题】:Non-trivial transform of XML using XSLT 1.0使用 XSLT 1.0 对 XML 进行非平凡的转换
【发布时间】:2017-04-19 06:14:47
【问题描述】:

我正在尝试使用 XSLT 将 XML 从一种格式转换为另一种格式,但这很复杂(至少对我而言),我不确定如何继续。我需要做以下逻辑:

(用类似 C# 的伪代码编写)

  1. 根据第四个 Axis 元素(如果存在)的内容更新每个 Machine 的 Top 元素,但仅当 Type 子元素的内容具有值“Rotary”时。如果满足这个条件,那么 Top 的格式应该是这样的:

    <Top>
        <Axis>xxx</Axis> 
        <IsIndexed>false</IsIndexed>
        <IsManual>false</IsManual>
    </Top>
    

其中 xxx 是 AxisID/Name 元素的值。

  1. 将 的内容替换为与第 1 项中所述相同的条件,但要检查第五个 Axis 元素(与第 1 项中检查的第四个元素相反)。

    李>
  2. 根据每台机器的第四和第五轴元素的内容更新模式元素。如果第四轴和第五轴的 Type 元素的值都为 Rotary,则 Mode 的值为 256。如果其中只有一个轴的值​​为rotary,则 Mode 的值为 128。如果两者都没有值 Rotary,则值为模式元素应为 0。

  3. 删除当前的 Ordering、IsIndexed 和 IsManual 元素。这个目前已经实施,但我想知道这是否需要根据我在上面 1-3 中列出的新要求进行更改

XSLT:(我目前拥有的)

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:cd="http://schemas.datacontract.org/2004/07/CMachine" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <xsl:output method="xml" indent="yes" />
  <!-- Copy everything not subject to the exceptions below -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>

  <!-- Ignore the ordering IsIndexed, IsManual elements -->
  <xsl:template match="cd:Ordering|cd:IsIndexed|cd:IsManual" />

</xsl:stylesheet>

输入:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfMachine xmlns="http://schemas.datacontract.org/2004/07/CMachine" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Machine>
    <Price>120000</Price>
    <Properties>
      <Axes>
        <Axis>
          <AxisID>
            <Name>X</Name>
            <Type>X</Type>
          </AxisID>
          <Type>Linear</Type>
        </Axis>
        <Axis>
          <AxisID>
            <Name>Y</Name>
            <Type>Y</Type>
          </AxisID>
          <Type>Linear</Type>
        </Axis>
        <Axis>
          <AxisID>
            <Name>Z</Name>
            <Type>Z</Type>
          </AxisID>
          <Type>Linear</Type>
        </Axis>
        <Axis>
          <AxisID>
            <Name>R1</Name>
            <Type>B</Type>
          </AxisID>
          <Type>Rotary</Type>
        </Axis>
        <Axis>
          <AxisID>
            <Name>R2</Name>
            <Type>C</Type>
          </AxisID>
          <Type>Linear</Type>
        </Axis>
      </Axes>
      <Ordering>XR1YR2Z</Ordering>
      <Rotaries>
        <Top i:nil="true" />
        <Bottom i:nil="true"/>
        <IsIndexed>false</IsIndexed>
        <IsManual>false</IsManual>
        <Mode>222</Mode>
      </Rotaries>
    </Properties>
  </Machine>
</ArrayOfMachine>

期望的输出:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfMachine xmlns="http://schemas.datacontract.org/2004/07/CMachine" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Machine>
    <Price>120000</Price>
    <Properties>
      <Axes>
        <Axis>
          <AxisID>
            <Name>X</Name>
        <Type>X</Type>
          </AxisID>
          <Type>Linear</Type>
        </Axis>
        <Axis>
          <AxisID>
            <Name>Y</Name>
            <Type>Y</Type>
          </AxisID>
          <Type>Linear</Type>
        </Axis>
        <Axis>
          <AxisID>
            <Name>Z</Name>
            <Type>Z</Type>
          </AxisID>
          <Type>Linear</Type>
        </Axis>
        <Axis>
          <AxisID>
            <Name>R1</Name>
            <Type>B</Type>
          </AxisID>
          <Type>Rotary</Type>
        </Axis>
        <Axis>
          <AxisID>
            <Name>R2</Name>
            <Type>C</Type>
          </AxisID>
          <Type>Linear</Type>
        </Axis>
      </Axes>
      <Ordering>XR1YR2Z</Ordering>
      <Rotaries>
        <Top>
             <Axis>R1</Axis> 
                     <IsIndexed>false</IsIndexed>
                     <IsManual>false</IsManual>
        </Top>
        <Bottom i:nil="true" /> 
        <Mode>128</Mode> 
      </Rotaries>
    </Properties>
  </Machine>
</ArrayOfMachine>

任何帮助将不胜感激!

【问题讨论】:

  • 我不明白你的伪代码 - 请用简单的英语解释所需的逻辑。
  • @michael.hor257k 我试图更清楚。让我知道是否仍有歧义。

标签: xml xslt xpath


【解决方案1】:

这是一个修改MachineTop 元素的示例,该Machine 的第四个AxisType 值为"Rotary"。新的Axis 元素的值取自上述AxisAxisID/Name 元素。

我相信您应该能够将此扩展到其他两个任务。

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:cd="http://schemas.datacontract.org/2004/07/CMachine"
xmlns="http://schemas.datacontract.org/2004/07/CMachine"
exclude-result-prefixes="cd">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="cd:Machine/cd:Properties[cd:Axes/cd:Axis[4]/cd:Type='Rotary']/cd:Rotaries/cd:Top">
    <xsl:copy>
        <Axis>
            <xsl:value-of select="ancestor::cd:Properties/cd:Axes/cd:Axis[4]/cd:AxisID/cd:Name"/>
        </Axis> 
        <IsIndexed>false</IsIndexed>
        <IsManual>false</IsManual>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

【讨论】:

  • 这个答案似乎解决了除第 3 项之外的所有问题。不知道如何处理 Rotary 类型的轴数的计数,然后根据该计数设置元素的值。
  • 计算任何和所有类型为 Rotary 的轴是否足够?或者是否有必要将计数限制为仅此类型的轴 #4 和 #5?
  • 总计数。另外,如果我想修改顶部元素以表示满足此条件的第一个轴,它将是 cd:Machine/cd:Properties[cd:Axes/cd:Axis/cd:Type='Rotary'][1]/ cd:Rotaries/cd:Top?如果是这样,语句的价值是什么?如果更合适,我可以将其作为一个单独的问题提出。
  • Mode的上下文中,你可以使用count(ancestor::cd:Properties/cd:Axes/cd:Axis[cd:Type='Rotary'])。我相信您想将其乘以 128 以获得最终值。 -- 是的,我认为最好开始一个新问题。
  • 所以 ?如果是这样,我不断得到一个值0.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-31
  • 1970-01-01
相关资源
最近更新 更多