【问题标题】:Split Comma Value to Separate nodes/elements XSLT拆分逗号值以分隔节点/元素 XSLT
【发布时间】:2021-05-11 19:17:40
【问题描述】:

我有一个场景,在其中一个 XML 字段中,源应用程序正在发送一个逗号分隔的值(根据它们的限制),但我们的目标系统只接受一个字段中的单个值(不需要 id 排序)。任何人都可以在这种情况下提供帮助。提前致谢!

当前 XML

<root>
    <order>
        <id>1</id>
        <value>RU</value>
    </order>
    <order>
        <id>2</id>
        <value>SA</value>
    </order>
    <order>
        <id>3</id>
        <value>MX,BR,US</value>
    </order>
    <order>
        <id>4</id>
        <value>IN,SL</value>
    </order>
</root>

预期输出:

<root>
    <order>
        <id>1</id>
        <value>RU</value>
    </order>
    <order>
        <id>2</id>
        <value>SA</value>
    </order>
    <order>
        <id>3</id>
        <value>MX</value>
    </order>
    <order>
        <id>4</id>
        <value>IN</value>
    </order>
    <order>
        <id>3</id>
        <value>BR</value>
    </order>
    <order>
        <id>3</id>
        <value>US</value>
    </order>
    <order>
        <id>4</id>
        <value>SL</value>
    </order>
</root>

【问题讨论】:

    标签: xml xslt xslt-1.0 xslt-2.0 xslt-3.0


    【解决方案1】:

    您可以像这样使用tokenize() 函数:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="3.0">
    
      <xsl:mode on-no-match="shallow-copy"/>
    
      <xsl:output method="xml" indent="yes"/>
    
      <xsl:template match="order[contains(value,',')]">
        <xsl:variable name="currentOrder" select="."/>
        <xsl:for-each select="tokenize(value,',')">
          <order>
            <id><xsl:value-of select="$currentOrder/id"/></id>
            <value><xsl:value-of select="."/></value>
          </order>
        </xsl:for-each>
      </xsl:template>
      
    </xsl:stylesheet>
    

    在这里查看它的工作原理:https://xsltfiddle.liberty-development.net/nbiE19Y

    【讨论】:

    • 好答案,我这边+1!
    【解决方案2】:

    如果您在一个带有 的系统上——它依赖于,因此只支持——你可以说,

    xmlstarlet sel \
    -t -m 'root' \
        -e '{name()}' -n \
          -m 'order' \
            --var nid='id' \
            -m 'str:tokenize(value,",")' \
              -e 'order' \
                -c '$nid' \
                -e 'value' -v '.' -b \
              -b -n \
    file.xml
    

    在哪里

    • -txsl:template 匹配 /
    • -m 映射到 xsl:for-each
    • -exsl:element
    • -cxsl:copy-of
    • -vxsl:value-of
    • -b 结束当前容器 (-m. -e, ...);仅需要 如果有任何模板选项(在-t 之后)
    • -n 输出换行符
    • str:tokenize 是 EXSLT 工作的一部分
    • 缩进和续行字符是可选的
    • 你的&lt;o/&gt;&lt;o/&gt; 眼神会找到片刻的解脱

    输出:

    <root>
    <order><id>1</id><value>RU</value></order>
    <order><id>2</id><value>SA</value></order>
    <order><id>3</id><value>MX</value></order>
    <order><id>3</id><value>BR</value></order>
    <order><id>3</id><value>US</value></order>
    <order><id>4</id><value>IN</value></order>
    <order><id>4</id><value>SL</value></order>
    </root>
    

    要列出生成的 XSLT 代码,请在 -t 选项之前添加 -C

    <?xml version="1.0"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:str="http://exslt.org/strings" xmlns:exslt="http://exslt.org/common" version="1.0" extension-element-prefixes="exslt str">
      <xsl:output omit-xml-declaration="yes" indent="no"/>
      <xsl:template match="/">
        <xsl:for-each select="root">
          <xsl:element name="{name()}">
            <xsl:value-of select="'&#10;'"/>
            <xsl:for-each select="order">
              <xsl:variable select="id" name="nid"/>
              <xsl:for-each select="str:tokenize(value,&quot;,&quot;)">
                <xsl:element name="order">
                  <xsl:copy-of select="$nid"/>
                  <xsl:element name="value">
                    <xsl:call-template name="value-of-template">
                      <xsl:with-param name="select" select="."/>
                    </xsl:call-template>
                  </xsl:element>
                </xsl:element>
                <xsl:value-of select="'&#10;'"/>
              </xsl:for-each>
            </xsl:for-each>
          </xsl:element>
        </xsl:for-each>
      </xsl:template>
      <xsl:template name="value-of-template">
        <xsl:param name="select"/>
        <xsl:value-of select="$select"/>
        <xsl:for-each select="exslt:node-set($select)[position()&gt;1]">
          <xsl:value-of select="'&#10;'"/>
          <xsl:value-of select="."/>
        </xsl:for-each>
      </xsl:template>
    </xsl:stylesheet>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-11
      • 1970-01-01
      相关资源
      最近更新 更多