在CDATA响应中制作for-each

时间:2017-07-16 18:34:10

标签: xml xslt

我是XSLT世界的新手,所以如果我不使用正确的条款,请原谅我。

我需要与外部系统进行集成,此系统返回一个包含在CDATA中的字符串,类似于:

<Response xmlns="http://tempuri.org/">
    <Result>
        <![CDATA[
  <resultcode>0</resultcode>
  <message>OK</message>
  <data>&lt;unitlist version="1"&gt;&lt;unit version="1" unitid="%" abbreviation="%" name="Porcentaje" /&gt;
  &lt;unit version="1" unitid="1/2 lb." abbreviation="1/2 lb." name="1/2 libra" /&gt;&lt;unit version="1" unitid="1/2 pt." abbreviation="1/2 pt." name="medias pintas" /&gt;&lt;unit version="1" unitid="1/2 pulg." abbreviation="1/2 pulg." name="1/2 pulg." /&gt;&lt;unit version="1" unitid="1/2&amp;quot; cdr." abbreviation="1/2&amp;quot; cdr." name="1/2 pulgada cuadrada" /&gt;&lt;/unitlist&gt;</data>
        ]]>
    </Result>
</Response>

我需要检索数据节点,并将每个单元解析成如下所示:

<units>
    <unit>
        <id>%</id>
        <name>Porcentaje</name>
        <abbreviation>%</abbreviation>
    </unit>
    <unit>
        <id>1/2 lb.</id>
        <name>1/2 libra</name>
        <abbreviation>1/2 lb.</abbreviation>
    </unit>
</units>

我一直在阅读有关两个阶段转换的信息,并尝试使用以下方法将数据包装到变量中:

<xsl:value-of select="substring-before(substring-after(., '&lt;data&gt;'), '&lt;/data&gt;')" disable-output-escaping="yes" />

它适用于转义文本标记和获取节点,但我无法使用它来迭代for-each并创建我需要的XML。

我需要在一个XSLT中执行此操作。

高级谢谢你的帮助。

2 个答案:

答案 0 :(得分:0)

这是我见过的最恐怖的XML。

将此XML解析为树后,您会发现有一个文本节点包含:

<resultcode>0</resultcode>
  <message>OK</message>
  <data>&lt;unitlist version="1"&gt;&lt;unit version="1" unitid="%" abbreviation="%" name="Porcentaje" /&gt;
  &lt;unit version="1" unitid="1/2 lb." abbreviation="1/2 lb." name="1/2 libra" /&gt;&lt;unit version="1" unitid="1/2 pt." abbreviation="1/2 pt." name="medias pintas" /&gt;&lt;unit version="1" unitid="1/2 pulg." abbreviation="1/2 pulg." name="1/2 pulg." /&gt;&lt;unit version="1" unitid="1/2&amp;quot; cdr." abbreviation="1/2&amp;quot; cdr." name="1/2 pulgada cuadrada" /&gt;&lt;/unitlist&gt;</data>

,它是sort-of-xml,除了它没有包含的包装元素。因此,您需要将此文本节点作为字符串提取,将其包装在虚拟元素中,然后使用XML解析器对其进行解析。

当你完成这项工作后,你将拥有一棵树,其中有一个文本节点(数据元素的子节点)包含内容:

<unitlist version="1"><unit version="1" unitid="%" abbreviation="%" name="Porcentaje" />
  <unit version="1" unitid="1/2 lb." abbreviation="1/2 lb." name="1/2 libra" /><unit version="1" unitid="1/2 pt." abbreviation="1/2 pt." name="medias pintas" /><unit version="1" unitid="1/2 pulg." abbreviation="1/2 pulg." name="1/2 pulg." /><unit version="1" unitid="1/2&quot; cdr." abbreviation="1/2" cdr." name="1/2 pulgada cuadrada" /></unitlist></data>

哪个是XML ...所以您可以通过XML解析器,之后您将能够使用通常的XML API来访问@unitid等属性的内容。

任何设计这个的人都有一种变态的幽默感。这是一种奇怪的心态,使用“半磅”作为一个重量单位。

答案 1 :(得分:0)

  

我需要检索数据节点,并将每个单元解析成一些东西   像这样:

您的数据提供程序不希望您解析给定的XML。他们遇到了很多麻烦,让你感到特别困难。如果你不能说服他们改变他们的格式,那么我建议你采取以下步骤:

第1步:将以下样式表应用于输入XML:

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

<xsl:template match="/ns:Response">
    <result>
        <xsl:value-of select="ns:Result" disable-output-escaping="yes"/>
    </result>
</xsl:template>

</xsl:stylesheet>

并将结果保存到文件

第2步:将以下样式表应用于步骤1中生成的文件:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/result">
    <xsl:value-of select="data" disable-output-escaping="yes"/>
</xsl:template>

</xsl:stylesheet>

并将结果保存到文件

第3步:将以下样式表应用于步骤2中生成的文件:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/unitlist">
    <units>
        <xsl:for-each select="unit">
            <xsl:copy>
                <id>
                    <xsl:value-of select="@unitid" />
                </id>
                <name>
                    <xsl:value-of select="@name" />
                </name>
                <abbreviation>
                    <xsl:value-of select="@abbreviation" />
                </abbreviation>
            </xsl:copy>
        </xsl:for-each>
    </units>
</xsl:template>

</xsl:stylesheet>

为清楚起见,这些是您应该在每个步骤中获得的结果:

第1步

<?xml version="1.0" encoding="UTF-8"?>
<result>

  <resultcode>0</resultcode>
  <message>OK</message>
  <data>&lt;unitlist version="1"&gt;&lt;unit version="1" unitid="%" abbreviation="%" name="Porcentaje" /&gt;
  &lt;unit version="1" unitid="1/2 lb." abbreviation="1/2 lb." name="1/2 libra" /&gt;&lt;unit version="1" unitid="1/2 pt." abbreviation="1/2 pt." name="medias pintas" /&gt;&lt;unit version="1" unitid="1/2 pulg." abbreviation="1/2 pulg." name="1/2 pulg." /&gt;&lt;unit version="1" unitid="1/2&amp;quot; cdr." abbreviation="1/2&amp;quot; cdr." name="1/2 pulgada cuadrada" /&gt;&lt;/unitlist&gt;</data>

    </result>

第2步

<?xml version="1.0" encoding="UTF-8"?>
<unitlist version="1"><unit version="1" unitid="%" abbreviation="%" name="Porcentaje" />
  <unit version="1" unitid="1/2 lb." abbreviation="1/2 lb." name="1/2 libra" /><unit version="1" unitid="1/2 pt." abbreviation="1/2 pt." name="medias pintas" /><unit version="1" unitid="1/2 pulg." abbreviation="1/2 pulg." name="1/2 pulg." /><unit version="1" unitid="1/2&quot; cdr." abbreviation="1/2&quot; cdr." name="1/2 pulgada cuadrada" /></unitlist>

第3步

<?xml version="1.0" encoding="UTF-8"?>
<units>
  <unit>
    <id>%</id>
    <name>Porcentaje</name>
    <abbreviation>%</abbreviation>
  </unit>
  <unit>
    <id>1/2 lb.</id>
    <name>1/2 libra</name>
    <abbreviation>1/2 lb.</abbreviation>
  </unit>
  <unit>
    <id>1/2 pt.</id>
    <name>medias pintas</name>
    <abbreviation>1/2 pt.</abbreviation>
  </unit>
  <unit>
    <id>1/2 pulg.</id>
    <name>1/2 pulg.</name>
    <abbreviation>1/2 pulg.</abbreviation>
  </unit>
  <unit>
    <id>1/2" cdr.</id>
    <name>1/2 pulgada cuadrada</name>
    <abbreviation>1/2" cdr.</abbreviation>
  </unit>
</units>

另一种方法是使用字符串函数提取数据,这将非常繁琐且容易出错。