admin管理员组

文章数量:1431262

First I have to say, that I'm no expert in XML/XSLT transforming. So please be patient. I have the following XML structure.

<cac:InvoiceLine>
    <cbc:ID>1</cbc:ID>
    <cbc:Note>Some remark text</cbc:Note>
    <cbc:Note>Charge: 1234567*</cbc:Note>
    <cbc:Note>Quantity: 1000*</cbc:Note>
    <cbc:Note>Charge: 987654*</cbc:Note>
    <cbc:Note>Quantity: 5000*</cbc:Note>
    ...
</cac:InvoiceLine>

The Charge and Quantity are connected. Charge 1234567 has a Quantity of 1000 kg. Now I want to loop through the list and print all connected data in one (!) line like:

1000 kg Charge 1234567

5000 kg Charge 987654

I've tried the following code, but actually this code is printing a new line for each <cbc:Note> field.

<xsl:for-each select="./cbc:Note">
  <xsl:choose>
    <xsl:when test="contains(.,'Charge:')">
      <xsl:value-of select="substring-before(substring-after(.,'Charge:'),'*')"/>
      <br />
    </xsl:when>
    <xsl:when test="contains(.,'Menge:')">
      <xsl:value-of select="substring-before(substring-after(.,'Quantity:'),'*')"/>
      <br />
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="."/>
      <br />
    </xsl:otherwise>
  </xsl:choose>
</xsl:for-each>

Any ideas how to solve this?

First I have to say, that I'm no expert in XML/XSLT transforming. So please be patient. I have the following XML structure.

<cac:InvoiceLine>
    <cbc:ID>1</cbc:ID>
    <cbc:Note>Some remark text</cbc:Note>
    <cbc:Note>Charge: 1234567*</cbc:Note>
    <cbc:Note>Quantity: 1000*</cbc:Note>
    <cbc:Note>Charge: 987654*</cbc:Note>
    <cbc:Note>Quantity: 5000*</cbc:Note>
    ...
</cac:InvoiceLine>

The Charge and Quantity are connected. Charge 1234567 has a Quantity of 1000 kg. Now I want to loop through the list and print all connected data in one (!) line like:

1000 kg Charge 1234567

5000 kg Charge 987654

I've tried the following code, but actually this code is printing a new line for each <cbc:Note> field.

<xsl:for-each select="./cbc:Note">
  <xsl:choose>
    <xsl:when test="contains(.,'Charge:')">
      <xsl:value-of select="substring-before(substring-after(.,'Charge:'),'*')"/>
      <br />
    </xsl:when>
    <xsl:when test="contains(.,'Menge:')">
      <xsl:value-of select="substring-before(substring-after(.,'Quantity:'),'*')"/>
      <br />
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="."/>
      <br />
    </xsl:otherwise>
  </xsl:choose>
</xsl:for-each>

Any ideas how to solve this?

Share Improve this question asked Nov 19, 2024 at 9:09 dns_nxdns_nx 3,9435 gold badges45 silver badges77 bronze badges 10
  • How exactly are Charge and Quantity "connected"? Is every Charge followed immediately by its Quantity? – michael.hor257k Commented Nov 19, 2024 at 9:15
  • Yes, the lines in cbc:Note are written below each other. So first is Chargeprinted, then the connected Quantity – dns_nx Commented Nov 19, 2024 at 9:32
  • 2 Which XSLT processor and/or which XSLT version do you use? In XSLT 2 or later it seems you could use <xsl:for-each-group select="cbc:Note" group-starting-with="cbc:Note[starts-with(., 'Charge:')]"> – Martin Honnen Commented Nov 19, 2024 at 9:40
  • Yes, Version 2. I will try your idea. Thanks – dns_nx Commented Nov 19, 2024 at 11:37
  • Maybe not after all. I receive the warning: The element 'template' in namespace 'http://www.w3./1999/XSL/Transform' has invalid child element 'for-each-group' in namespace 'http://www.w3./1999/XSL/Transform'. List of possible elements expected: 'apply-templates, call-template, apply-imports, for-each, value-of, copy-of, number, choose, if, text, copy, variable, message, fallback, processing-instruction, comment, element, attribute' in namespace 'http://www.w3./1999/XSL/Transform' as well as any element in namespace '##other'. – dns_nx Commented Nov 19, 2024 at 11:39
 |  Show 5 more comments

1 Answer 1

Reset to default 2

Try something like:

<xsl:template match="cac:InvoiceLine">
    <xsl:for-each select="cbc:Note[starts-with(., 'Charge: ')]">
        <xsl:value-of select="substring-before(substring-after(following-sibling::cbc:Note[1], 'Quantity: '), '*')"/>
        <xsl:text> kg </xsl:text>
        <xsl:value-of select="substring-before(., '*')"/>
        <br/>
    </xsl:for-each>
</xsl:template>

You can see it working here.

本文标签: XSLTHow to loop through each entrybut print out one lineStack Overflow