MakeXmlElement.java 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // Copyright (c) 2010 Per M.A. Bothner
  2. // This is free software; for terms and warranty disclaimer see ../../../COPYING.
  3. package gnu.kawa.lispexpr;
  4. import gnu.expr.*;
  5. import gnu.lists.*;
  6. import gnu.xml.*;
  7. import gnu.kawa.xml.*;
  8. import gnu.bytecode.ClassType;
  9. import gnu.mapping.*;
  10. import kawa.lang.*;
  11. /** A Syntax transformer for a XML constructor.
  12. * This is needed to put namespace declarations in the lexical scope.
  13. */
  14. public class MakeXmlElement extends Syntax
  15. {
  16. public static final MakeXmlElement makeXml = new MakeXmlElement();
  17. static { makeXml.setName("$make-xml$"); }
  18. static final ClassType typeNamespace =
  19. ClassType.make("gnu.mapping.Namespace");
  20. public Expression rewriteForm (Pair form, Translator tr)
  21. {
  22. Pair pair1 = (Pair) form.getCdr();
  23. Object namespaceList = pair1.getCar();
  24. Object obj = pair1.getCdr();
  25. boolean nsSeen = false;
  26. NamespaceBinding saveBindings = tr.xmlElementNamespaces;
  27. NamespaceBinding nsBindings = saveBindings;
  28. while (namespaceList instanceof Pair)
  29. {
  30. if (! nsSeen)
  31. {
  32. tr.letStart();
  33. nsSeen = true;
  34. }
  35. Pair namespacePair = (Pair) namespaceList;
  36. Pair namespaceNode = (Pair) namespacePair.getCar();
  37. String nsPrefix = namespaceNode.getCar().toString();
  38. nsPrefix = nsPrefix.length() == 0 ? null : nsPrefix.intern();
  39. Object valueList = namespaceNode.getCdr();
  40. StringBuilder sbuf = new StringBuilder();
  41. while (valueList instanceof Pair)
  42. {
  43. Pair valuePair = (Pair) valueList;
  44. Object valueForm = valuePair.getCar();
  45. Object value;
  46. if (LList.listLength(valueForm, false) == 2
  47. && valueForm instanceof Pair
  48. && ((Pair) valueForm).getCar() == ReaderXmlElement.xmlTextSymbol)
  49. {
  50. value = ((Pair) ((Pair) valueForm).getCdr()).getCar();
  51. }
  52. else
  53. {
  54. Expression valueExp = tr.rewrite_car(valuePair, false);
  55. value = valueExp.valueIfConstant();
  56. }
  57. if (value == null)
  58. {
  59. Object savePos = tr.pushPositionOf(valuePair);
  60. tr.error('e', "namespace URI must be literal");
  61. tr.popPositionOf(savePos);
  62. }
  63. else
  64. sbuf.append(value);
  65. valueList = valuePair.getCdr();
  66. }
  67. String nsUri = sbuf.toString().intern();
  68. // FIXME: check for duplicate prefix
  69. // FIXME: check that uri not same as predefined xml namespace
  70. // FIXME: check that prefix isn't "xml" or "xmlns"
  71. nsBindings
  72. = new NamespaceBinding(nsPrefix,
  73. nsUri == "" ? null : nsUri,
  74. nsBindings);
  75. Namespace namespace;
  76. if (nsPrefix == null)
  77. {
  78. namespace = Namespace.valueOf(nsUri);
  79. nsPrefix = ReaderXmlElement.DEFAULT_ELEMENT_NAMESPACE;
  80. }
  81. else
  82. {
  83. namespace = XmlNamespace.getInstance(nsPrefix, nsUri);
  84. }
  85. Symbol nsSymbol = Namespace.EmptyNamespace.getSymbol(nsPrefix);
  86. Declaration decl = tr.letVariable(nsSymbol, typeNamespace,
  87. new QuoteExp(namespace));
  88. decl.setFlag(Declaration.IS_CONSTANT|Declaration.IS_NAMESPACE_PREFIX|Declaration.TYPE_SPECIFIED);
  89. // FIXME: Translator.setLine(decl, p1);
  90. namespaceList = namespacePair.getCdr();
  91. }
  92. // if (namespaceList != LList.Empty) ERROR;
  93. MakeElement mkElement = new MakeElement();
  94. mkElement.setNamespaceNodes(nsBindings);
  95. mkElement.setStringIsText(true);
  96. tr.xmlElementNamespaces = nsBindings;
  97. try
  98. {
  99. if (nsSeen)
  100. tr.letEnter();
  101. Expression result = tr.rewrite(Translator.makePair(form, mkElement, obj));
  102. return nsSeen ? tr.letDone(result) : result;
  103. }
  104. finally
  105. {
  106. tr.xmlElementNamespaces = saveBindings;
  107. }
  108. }
  109. }