ProtoStyledStringDecoder { @NotNull public static String getRawXmlValue(@NotNull Resources.StyledString styledStringMsg) { String text = styledStringMsg.getValue(); StringBuilder xmlValue = new StringBuilder(text.length() * 2); List<Resources.StyledString.Span> spanList = styledStringMsg.getSpanList(); List<Resources.StyledString.Span> spanStack = new ArrayList<>(spanList.size()); int offset = 0; for (int i = 0; i <= styledStringMsg.getSpanCount(); i++) { int oldOffset = offset; Resources.StyledString.Span spanMsg; if (i < styledStringMsg.getSpanCount()) { spanMsg = styledStringMsg.getSpan(i); offset = spanMsg.getFirstChar(); } else { spanMsg = null; offset = text.length(); } while (!spanStack.isEmpty() && spanStack.get(spanStack.size() - 1).getLastChar() < offset) { Resources.StyledString.Span span = spanStack.remove(spanStack.size() - 1); int spanEnd = span.getLastChar() + 1; if (spanEnd > oldOffset) { XmlUtils.appendXmlTextValue(xmlValue, text, oldOffset, spanEnd); oldOffset = spanEnd; } String tagText = span.getTag(); int tagEnd = indexOfOrEnd(tagText, ';', 0); xmlValue.append("</").append(tagText, 0, tagEnd).append('>'); } if (offset >= oldOffset) { XmlUtils.appendXmlTextValue(xmlValue, text, oldOffset, offset); if (spanMsg != null) { String tagText = spanMsg.getTag(); int pos = indexOfOrEnd(tagText, ';', 0); if (pos != 0) { spanStack.add(spanMsg); xmlValue.append('<').append(tagText, 0, pos); while (pos < tagText.length()) { pos++; int nextPos = indexOfOrEnd(tagText, ';', pos); int nameEnd = tagText.indexOf('=', pos); if (nameEnd > pos && nameEnd < nextPos) { xmlValue.append(' '); xmlValue.append(tagText, pos, nameEnd + 1); xmlValue.append('"'); XmlUtils.appendXmlAttributeValue(xmlValue, tagText, nameEnd + 1, nextPos); xmlValue.append('"'); } pos = nextPos; } xmlValue.append('>'); } } } } return xmlValue.toString(); } private  ProtoStyledStringDecoder(); @NotNull static String getRawXmlValue(@NotNull Resources.StyledString styledStringMsg);  }
@Test public void testRawXmlValue() throws Exception { StyledString.Builder builder = StyledString.newBuilder(); TextFormat.merge(STYLED_STRING_PROTO, ExtensionRegistry.getEmptyRegistry(), builder); StyledString styledString = builder.build(); assertEquals(STYLED_STRING_XML, ProtoStyledStringDecoder.getRawXmlValue(styledString)); }