Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml 使用身份转换优化XSLT_Xml_Xslt - Fatal编程技术网

Xml 使用身份转换优化XSLT

Xml 使用身份转换优化XSLT,xml,xslt,Xml,Xslt,我最近遇到了以下股票代码XML提要: <?xml version="1.0" encoding="utf-8"?> <BloombergOutput> <BloombergOutput CreatedUtc="2011-08-11T20:40:50.8851936Z"> <Instruments> <Instrument Symbol="BLL"> <Fields>

我最近遇到了以下股票代码XML提要:

<?xml version="1.0" encoding="utf-8"?>
<BloombergOutput>
  <BloombergOutput CreatedUtc="2011-08-11T20:40:50.8851936Z">
    <Instruments>
      <Instrument Symbol="BLL">
        <Fields>
          <Field1 Name="LastPrice">
            <Value>35.550000</Value>
          </Field1>
          <Field2 Name="NetChangeOneDay">
            <Value>+1.550000</Value>
          </Field2>
          <Field3 Name="LastCloseDate">
            <Value>08/11/2011</Value>
          </Field3>
          <Field4 Name="LastClosePrice">
            <Value>35.550000</Value>
          </Field4>
          <Field5 Name="UpdateDate">
            <Value>08/11/2011</Value>
          </Field5>
          <Field6 Name="UpdateTime">
            <Value>16:15:03</Value>
          </Field6>
          <Field7 Name="LongName">
            <Value>Ball Corp</Value>
          </Field7>
          <Field8 Name="Name">
            <Value>BALL CORP</Value>
          </Field8>
          <Field9 Name="PriceSource">
            <Value>US</Value>
          </Field9>
          <Field10 Name="SymbolType">
            <Value>Common Stock</Value>
          </Field10>
        </Fields>
      </Instrument>
    </Instruments>
  </BloombergOutput>
</BloombergOutput>

35.550000
+1.550000
08/11/2011
35.550000
08/11/2011
16:15:03
鲍尔公司
鲍尔公司
美国
普通股
我想使用XSLT将这个提要转换成没有不必要的标记嵌套、有更多描述性元素名称和截断过长的数字的内容,这样它们在小数点后只有两个数字。下面是我提出的XSLT:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="no" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <!-- Identity Transform, modified to begin at the Instruments element -->
  <xsl:template match="BloombergOutput/BloombergOutput/Instruments/@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- For each instrument, we grab the Symbol attribute and work on each child element -->
  <xsl:template match="Instrument">
    <Instrument>
      <Symbol><xsl:value-of select="@Symbol" /></Symbol>
      <xsl:apply-templates select="Fields/*" mode="fields" />
    </Instrument>
  </xsl:template>

  <!-- For each child field, we create a newly-named one and give it a value -->
  <xsl:template match="node()" mode="fields">

    <xsl:variable
      name="FieldName"
      select="@Name" />
    <xsl:variable
        name="Value"
        select="Value" />

    <xsl:element name="{$FieldName}">
      <xsl:choose>
        <!-- For these fields, we only want to preserve to spots after the decimal point -->
        <xsl:when test="$FieldName='LastPrice' or $FieldName='NetChangeOneDay' or $FieldName='LastClosePrice'">
          <xsl:value-of select="concat(substring-before($Value, '.'), '.', substring(substring-after($Value, '.'), 1, 2))" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$Value" />
        </xsl:otherwise>
      </xsl:choose>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

…生成此输出:

<?xml version="1.0"?>
<BloombergOutput>
  <BloombergOutput>2011-08-11T20:40:50.8851936Z
    <Instruments>
      <Instrument>
        <Symbol>BLL</Symbol>
        <LastPrice>35.55</LastPrice>
        <NetChangeOneDay>+1.55</NetChangeOneDay>
        <LastCloseDate>08/11/2011</LastCloseDate>
        <LastClosePrice>35.55</LastClosePrice>
        <UpdateDate>08/11/2011</UpdateDate>
        <UpdateTime>16:15:03</UpdateTime>
        <LongName>Ball Corp</LongName>
        <Name>BALL CORP</Name>
        <PriceSource>US</PriceSource>
        <SymbolType>Common Stock</SymbolType>
      </Instrument>
    </Instruments>
  </BloombergOutput>
</BloombergOutput>

2011-08-11T20:40:50.8851936Z
BLL
35.55
+1.55
08/11/2011
35.55
08/11/2011
16:15:03
鲍尔公司
鲍尔公司
美国
普通股
虽然这几乎是我想要的,但也存在一些问题:

  • 顶部的附加
    BloombergOutput
    元素被保留;此外,它的
    CreatedUtc
    参数以一种非常奇怪的方式保留。我的初衷是完全删除不必要的
    BloombergOutput
    标记
  • 我成功插入了一个
    仪器
    标签。 但是,
    仪器
    在我未明确说明的情况下保留。 我知道身份转换带来了它,因为我没有 告诉它走开,但是如果我想要不同的开场元素呢 (比如,
    StockQuote
  • 我的目的是要善于使用身份转换。 然而,我不确定我的比赛修改是否正确 完成我正在做的事情的方法
  • 总的来说,我正在寻求您关于如何改进这一点的专家建议。请随时告诉我,我正试图在一个不属于它的设计模式中卡住。:)


    非常感谢。

    我想这是您正在寻找的机制:

    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output omit-xml-declaration="no" indent="yes"/>
        <xsl:strip-space elements="*"/>
    
        <!-- Get rid of the BloombergOutput, Instruments elements-->
        <xsl:template match="BloombergOutput|Instruments">
            <xsl:apply-templates/>
        </xsl:template>
        <!-- Identity Transform -->
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
    
        <!-- For each instrument, we grab the Symbol attribute and work on each child element -->
        <xsl:template match="Instrument">
            <Instrument>
                <Symbol><xsl:value-of select="@Symbol" /></Symbol>
                <xsl:apply-templates select="Fields/*" />
            </Instrument>
        </xsl:template>
    
        <!-- For each child field, we create a newly-named one and give it a value -->
        <xsl:template match="*[starts-with(name(),'Field')]">
    
            <xsl:variable
                name="FieldName"
                select="@Name" />
            <xsl:variable
                name="Value"
                select="Value" />
    
            <xsl:element name="{$FieldName}">
                <xsl:choose>
                    <!-- For these fields, we only want to preserve to spots after the decimal point -->
                    <xsl:when test="$FieldName='LastPrice' or $FieldName='NetChangeOneDay' or $FieldName='LastClosePrice'">
                        <xsl:value-of select="concat(substring-before($Value, '.'), '.', substring(substring-after($Value, '.'), 1, 2))" />
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="$Value" />
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:element>
        </xsl:template>
    </xsl:stylesheet>
    
    还有一句话,如果你有两个
    仪器
    元素,那么转换的结果将不会很好。

    好问题,+1

    这里有一个更简单、更短、更简洁的解决方案(没有变量,没有
    xsl:choose
    /
    xsl:when
    /
    xsl:when
    /
    否则,没有
    子字符串()
    ):

    <xsl:stylesheet version="1.0"
         xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
         <xsl:output omit-xml-declaration="yes" indent="yes"/>
         <xsl:strip-space elements="*"/>
    
         <xsl:template match="node()|@*">
             <xsl:copy>
               <xsl:apply-templates select="node()|@*"/>
             </xsl:copy>
         </xsl:template>
    
         <xsl:template match="BloombergOutput | Fields" priority="2">
          <xsl:apply-templates/>
         </xsl:template>
    
         <xsl:template match="*[starts-with(name(),'Field')]">
           <xsl:element name="{@Name}">
             <xsl:apply-templates/>
           </xsl:element>
         </xsl:template>
    
         <xsl:template match="Value">
          <xsl:apply-templates/>
         </xsl:template>
    
         <xsl:template match=
          "*[contains('|LastPrice|LastClosePrice|NetChangeOneDay|',
                      concat('|', @Name, '|')
                      )
            ]
              /Value
            ">
    
            <xsl:value-of select=
              "format-number(translate(.,'+', ''), '##0.00')"/>
         </xsl:template>
    </xsl:stylesheet>
    
    
    
    将此转换应用于提供的XML文档时

    <BloombergOutput>
      <BloombergOutput CreatedUtc="2011-08-11T20:40:50.8851936Z">
        <Instruments>
          <Instrument Symbol="BLL">
            <Fields>
              <Field1 Name="LastPrice">
                <Value>35.550000</Value>
              </Field1>
              <Field2 Name="NetChangeOneDay">
                <Value>+1.550000</Value>
              </Field2>
              <Field3 Name="LastCloseDate">
                <Value>08/11/2011</Value>
              </Field3>
              <Field4 Name="LastClosePrice">
                <Value>35.550000</Value>
              </Field4>
              <Field5 Name="UpdateDate">
                <Value>08/11/2011</Value>
              </Field5>
              <Field6 Name="UpdateTime">
                <Value>16:15:03</Value>
              </Field6>
              <Field7 Name="LongName">
                <Value>Ball Corp</Value>
              </Field7>
              <Field8 Name="Name">
                <Value>BALL CORP</Value>
              </Field8>
              <Field9 Name="PriceSource">
                <Value>US</Value>
              </Field9>
              <Field10 Name="SymbolType">
                <Value>Common Stock</Value>
              </Field10>
            </Fields>
          </Instrument>
        </Instruments>
      </BloombergOutput>
    </BloombergOutput>
    
    <Instruments>
       <Instrument Symbol="BLL">
          <LastPrice>35.55</LastPrice>
          <NetChangeOneDay>1.55</NetChangeOneDay>
          <LastCloseDate>08/11/2011</LastCloseDate>
          <LastClosePrice>35.55</LastClosePrice>
          <UpdateDate>08/11/2011</UpdateDate>
          <UpdateTime>16:15:03</UpdateTime>
          <LongName>Ball Corp</LongName>
          <Name>BALL CORP</Name>
          <PriceSource>US</PriceSource>
          <SymbolType>Common Stock</SymbolType>
       </Instrument>
    </Instruments>
    
    
    35.550000
    +1.550000
    08/11/2011
    35.550000
    08/11/2011
    16:15:03
    鲍尔公司
    鲍尔公司
    美国
    普通股
    
    生成所需的正确结果

    <BloombergOutput>
      <BloombergOutput CreatedUtc="2011-08-11T20:40:50.8851936Z">
        <Instruments>
          <Instrument Symbol="BLL">
            <Fields>
              <Field1 Name="LastPrice">
                <Value>35.550000</Value>
              </Field1>
              <Field2 Name="NetChangeOneDay">
                <Value>+1.550000</Value>
              </Field2>
              <Field3 Name="LastCloseDate">
                <Value>08/11/2011</Value>
              </Field3>
              <Field4 Name="LastClosePrice">
                <Value>35.550000</Value>
              </Field4>
              <Field5 Name="UpdateDate">
                <Value>08/11/2011</Value>
              </Field5>
              <Field6 Name="UpdateTime">
                <Value>16:15:03</Value>
              </Field6>
              <Field7 Name="LongName">
                <Value>Ball Corp</Value>
              </Field7>
              <Field8 Name="Name">
                <Value>BALL CORP</Value>
              </Field8>
              <Field9 Name="PriceSource">
                <Value>US</Value>
              </Field9>
              <Field10 Name="SymbolType">
                <Value>Common Stock</Value>
              </Field10>
            </Fields>
          </Instrument>
        </Instruments>
      </BloombergOutput>
    </BloombergOutput>
    
    <Instruments>
       <Instrument Symbol="BLL">
          <LastPrice>35.55</LastPrice>
          <NetChangeOneDay>1.55</NetChangeOneDay>
          <LastCloseDate>08/11/2011</LastCloseDate>
          <LastClosePrice>35.55</LastClosePrice>
          <UpdateDate>08/11/2011</UpdateDate>
          <UpdateTime>16:15:03</UpdateTime>
          <LongName>Ball Corp</LongName>
          <Name>BALL CORP</Name>
          <PriceSource>US</PriceSource>
          <SymbolType>Common Stock</SymbolType>
       </Instrument>
    </Instruments>
    
    
    35.55
    1.55
    08/11/2011
    35.55
    08/11/2011
    16:15:03
    鲍尔公司
    鲍尔公司
    美国
    普通股
    
    谢谢您的回复。问题:为什么多个
    Instrument
    元素会导致格式不正确的结果?当您匹配Instruments元素时,您只有apply模板。这意味着对于每个工具子级,将触发模板工具,而不触发任何嵌入元素。您可以将测试(使用xsl:choose)添加到模板:if count(*)>1,然后创建一个englobing元素并在其中应用模板,否则只需apply-templates即可。谢谢,@Dimitre。我喜欢你的想法。但是,有两个注意事项:(1)当我运行此转换(使用xsltproc)时,我得到一个xsl:element:有效名称“”不是有效的QName。关于{@Name}值的错误;(2) 看起来对于某些字段,仍然有一个value元素——我的意图是去掉这些元素,并直接输出值。@ABach:很好。我没有注意到这一点,因为Saxon6.5.4(XSLT1.0处理器)有一个bug,并且转换成功。现在我使用Saxon 9.1.05(XSLT2.0处理器)运行它。我很快会更新我的答案。只需使用:``而不是``谢谢-这就解决了这个问题。最后一个呢(其中有我想要删除的无关的
    元素)?我希望所有字段都遵循
    的格式(而不是,比如说,
    )。非常感谢您的帮助。@ABach:我现在正在工作--请耐心等待--我会在5-6小时后调查此事。@ABach:我的理解正确吗?您想要的是:
    普通股而不是:
    普通股