const char* const RESOURCES_ROOT_NAMESPACE = "http://schemas.android.com/apk/res/";
const char* const RESOURCES_ANDROID_NAMESPACE = "http://schemas.android.com/apk/res/android";
+const char* const RESOURCES_ROOT_PRV_NAMESPACE = "http://schemas.android.com/apk/prv/res/";
const char* const XLIFF_XMLNS = "urn:oasis:names:tc:xliff:document:1.2";
const char* const ALLOWED_XLIFF_ELEMENTS[] = {
}
static const String16 RESOURCES_PREFIX(RESOURCES_ROOT_NAMESPACE);
+static const String16 RESOURCES_PRV_PREFIX(RESOURCES_ROOT_PRV_NAMESPACE);
-String16 getNamespaceResourcePackage(String16 namespaceUri)
+String16 getNamespaceResourcePackage(String16 namespaceUri, bool* outIsPublic)
{
//printf("%s starts with %s?\n", String8(namespaceUri).string(),
// String8(RESOURCES_PREFIX).string());
- if (!namespaceUri.startsWith(RESOURCES_PREFIX)) return String16();
+ size_t prefixSize;
+ bool isPublic = true;
+ if (namespaceUri.startsWith(RESOURCES_PREFIX)) {
+ prefixSize = RESOURCES_PREFIX.size();
+ } else if (namespaceUri.startsWith(RESOURCES_PRV_PREFIX)) {
+ isPublic = false;
+ prefixSize = RESOURCES_PRV_PREFIX.size();
+ } else {
+ if (outIsPublic) *outIsPublic = isPublic; // = true
+ return String16();
+ }
+
//printf("YES!\n");
- const size_t prefixSize = RESOURCES_PREFIX.size();
//printf("namespace: %s\n", String8(String16(namespaceUri, namespaceUri.size()-prefixSize, prefixSize)).string());
+ if (outIsPublic) *outIsPublic = isPublic;
return String16(namespaceUri, namespaceUri.size()-prefixSize, prefixSize);
}
}
spanStack.pop();
- if (empty) {
- fprintf(stderr, "%s:%d: WARNING: empty '%s' span found for at text '%s'\n",
+ /*
+ * This warning seems to be just an irritation to most people,
+ * since it is typically introduced by translators who then never
+ * see the warning.
+ */
+ if (0 && empty) {
+ fprintf(stderr, "%s:%d: warning: empty '%s' span found in text '%s'\n",
fileName, inXml->getLineNumber(),
- String8(*outString).string(), String8(spanTag).string());
+ String8(spanTag).string(), String8(*outString).string());
}
} else if (code == ResXMLTree::START_NAMESPACE) {
, mFilename(filename)
, mStartLineNumber(0)
, mEndLineNumber(0)
+ , mUTF8(false)
{
if (isNamespace) {
mNamespacePrefix = s1;
XMLNode::XMLNode(const String8& filename)
: mFilename(filename)
{
+ memset(&mCharsValue, 0, sizeof(mCharsValue));
}
XMLNode::type XMLNode::getType() const
return mChildren;
}
+const String8& XMLNode::getFilename() const
+{
+ return mFilename;
+}
+
const Vector<XMLNode::attribute_entry>&
XMLNode::getAttributes() const
{
return mAttributes;
}
+const XMLNode::attribute_entry* XMLNode::getAttribute(const String16& ns,
+ const String16& name) const
+{
+ for (size_t i=0; i<mAttributes.size(); i++) {
+ const attribute_entry& ae(mAttributes.itemAt(i));
+ if (ae.ns == ns && ae.name == name) {
+ return &ae;
+ }
+ }
+
+ return NULL;
+}
+
+XMLNode::attribute_entry* XMLNode::editAttribute(const String16& ns,
+ const String16& name)
+{
+ for (size_t i=0; i<mAttributes.size(); i++) {
+ attribute_entry * ae = &mAttributes.editItemAt(i);
+ if (ae->ns == ns && ae->name == name) {
+ return ae;
+ }
+ }
+
+ return NULL;
+}
+
const String16& XMLNode::getCData() const
{
return mChars;
return mEndLineNumber;
}
+sp<XMLNode> XMLNode::searchElement(const String16& tagNamespace, const String16& tagName)
+{
+ if (getType() == XMLNode::TYPE_ELEMENT
+ && mNamespaceUri == tagNamespace
+ && mElementName == tagName) {
+ return this;
+ }
+
+ for (size_t i=0; i<mChildren.size(); i++) {
+ sp<XMLNode> found = mChildren.itemAt(i)->searchElement(tagNamespace, tagName);
+ if (found != NULL) {
+ return found;
+ }
+ }
+
+ return NULL;
+}
+
+sp<XMLNode> XMLNode::getChildElement(const String16& tagNamespace, const String16& tagName)
+{
+ for (size_t i=0; i<mChildren.size(); i++) {
+ sp<XMLNode> child = mChildren.itemAt(i);
+ if (child->getType() == XMLNode::TYPE_ELEMENT
+ && child->mNamespaceUri == tagNamespace
+ && child->mElementName == tagName) {
+ return child;
+ }
+ }
+
+ return NULL;
+}
+
status_t XMLNode::addChild(const sp<XMLNode>& child)
{
if (getType() == TYPE_CDATA) {
return NO_ERROR;
}
+status_t XMLNode::insertChildAt(const sp<XMLNode>& child, size_t index)
+{
+ if (getType() == TYPE_CDATA) {
+ SourcePos(mFilename, child->getStartLineNumber()).error("Child to CDATA node.");
+ return UNKNOWN_ERROR;
+ }
+ //printf("Adding child %p to parent %p\n", child.get(), this);
+ mChildren.insertAt(child, index);
+ return NO_ERROR;
+}
+
status_t XMLNode::addAttribute(const String16& ns, const String16& name,
const String16& value)
{
for (size_t i=0; i<N; i++) {
const attribute_entry& e = mAttributes.itemAt(i);
if (e.ns.size() <= 0) continue;
- String16 pkg(getNamespaceResourcePackage(e.ns));
- NOISY(printf("Elem %s %s=\"%s\": namespace %s ===> %s\n",
+ bool nsIsPublic;
+ String16 pkg(getNamespaceResourcePackage(e.ns, &nsIsPublic));
+ NOISY(printf("Elem %s %s=\"%s\": namespace(%s) %s ===> %s\n",
String8(getElementName()).string(),
String8(e.name).string(),
String8(e.string).string(),
- String8(e.ns).string(), String8(pkg).string()));
+ String8(e.ns).string(),
+ (nsIsPublic) ? "public" : "private",
+ String8(pkg).string()));
if (pkg.size() <= 0) continue;
uint32_t res = table != NULL
- ? table->getResId(e.name, &attr, &pkg, &errorMsg)
+ ? table->getResId(e.name, &attr, &pkg, &errorMsg, nsIsPublic)
: assets->getIncludedResources().
identifierForName(e.name.string(), e.name.size(),
attr.string(), attr.size(),
status_t XMLNode::flatten(const sp<AaptFile>& dest,
bool stripComments, bool stripRawValues) const
{
- StringPool strings;
+ StringPool strings = StringPool(false, mUTF8);
Vector<uint32_t> resids;
// First collect just the strings for attribute names that have a