255

I am new to yaml, and I have a question about the pipe symbol (|) used for multiple lines. Does YAML have any syntax like the one below?

test: |6+

Of the two YAML files below, the first one is working and second is not. I do not know what is causing this.

First File

Name :
  -
   testing:
     val1
  -
   second:
     val2
  -
   third:
     val3
  -
   then
  - 
    final: |
     a
     aa
     aaa
     aaaa : 'test:'

Second File

Name :
  -
   testing:
     val1
  -
   second:
     val2
  -
   third:
     val3
  -
   then
  - 
    final: |6+
      a
      aa
      aaa
      aaaa : 'test:'

The second file is the customer's.

I am using XMLBeans and I get this error:

com.esotericsoftware.yamlbeans.parser.Parser$ParserException: Line 17, column 12: Expected a 'block end' but found: block mapping start".

Matt Lyons-Wood
  • 931
  • 11
  • 17

2 Answers2

330

The pipe symbol at the end of a line in YAML signifies that any indented text that follows should be interpreted as a multi-line scalar value. See the YAML spec.

Specifically, the pipe indicates that (except for the indentation) the scalar value should be interpreted literally in such a way that preserves newlines. Conversely, the > character indicates that multi-line "folded" scalar follows, meaning that newlines are converted to spaces. For example:

>>> import yaml
>>> yaml.load("""
... |
...  This is a multi-line
...  literal style scalar.
... """)
'This is a multi-line\nliteral style scalar.\n'
>>> yaml.load("""
... >
...  This is a multi-line
...  folded scalar; new lines are folded into
...  spaces.
... """)
'This is a multi-line folded scalar; new lines are folded into spaces.\n'

The 6+ part is the indentation indicator (an explicit specification of how many spaces of indentation should be used) with the "chomping indicator" + which controls how extra whitespace at the end of the scalar literal should be handled.

The error you're getting is a tricky one: It's because indentation should be relative to the current block-level element. So in this case it should be 2+ instead of 6+ because the last block-level element is the mapping final: and the literal is indented 2 from it. Updated with correction from @bramvi.

Iguananaut
  • 21,810
  • 5
  • 50
  • 63
  • 4
    Also look at [in-yaml-how-do-i-break-a-string-over-multiple-lines](https://stackoverflow.com/questions/3790454/in-yaml-how-do-i-break-a-string-over-multiple-lines) – Oliver Apr 12 '18 at 13:18
  • 2
    `So in this case it should be 4+ instead of 6+` I think it should be 2, not 4, because that's the relative indent there. Tested on `pyyaml 6.0`. – bravmi Oct 22 '21 at 11:55
  • 2
    @bravmi Good catch. 8+ years of this answer and no one pointed that out before. I agree. – Iguananaut Oct 22 '21 at 15:31
  • I don't recall why I made the justification for `4+` based on `final:` not being a block element. It clearly is. It's not a flow-style mapping without the `{ ... }`. – Iguananaut Oct 22 '21 at 15:36
  • Def. multi-line scalar: a multi-line string of dynamic size. In javascript, this is just known as a string. https://eemeli.org/yaml-playground/ – Ray Foss May 05 '22 at 18:25
41

The pipe is used when you want newlines to be kept as newlines.

For more information : https://yaml-multiline.info/

Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
freemanpolys
  • 1,848
  • 20
  • 19