1

I noticed that with VBO you can call the method getSingleNode to get a specific node object, is it possible to do something similar with office js?

Also, I have a radio button value in my Word metadata, I managed to access its customxmlnode object, then I used setTextsync method to change its value from true to false, but the new value I get for my radio button metadata is empty. Other text type metadata could be edited correctly though. Could anyone give some suggestions?

function EditCTF() {
  //$("#fields").css({ display: "" });
  Word.run(function(context) {
    context.document.properties.title = $("#Title").val();
    Office.context.document.customXmlParts.getByNamespaceAsync(
      "http://schemas.microsoft.com/office/2006/metadata/properties",
      function(asyncResult) {
        if (asyncResult.value.length > 0) {
          var xmlPart = asyncResult.value[0];

          xmlPart.getNodesAsync("*/*", function(nodeResults) {
            console.log(nodeResults.value.length);
            for (i = 0; i < nodeResults.value.length; i++) {
              var node = nodeResults.value[i];
              node.getTextAsync({ asyncContext: "StateNormal" }, function(result) {
                console.log(result);
                console.log(result.value);
              });

              console.log("NewValue");

              if (node.baseName == "Address") {
                node.setTextAsync(
                  $("#Address").val(),
                  {
                    asyncContext: "StateNormal"
                  },
                  function(newresult) {}
                );
              }

              if (node.baseName == "MainContactPerson") {
                node.setTextAsync(
                  $("#Main Contact Person").val(),
                  {
                    asyncContext: "StateNormal"
                  },
                  function(newresult) {}
                );
              }

              if (node.baseName == "GDPR") {
                node.setTextAsync(
                  "true",
                  {
                    asyncContext: "StateNormal"
                  },
                  function(newresult) {
                    console.log(newresult);
                    console.log(newresult.value);
                  }
                );
              }
            }
          });
        }
      }
    );
    return context.sync().then(function() {});
  });
}
Marc LaFleur
  • 31,987
  • 4
  • 37
  • 63
  • Could you add a code sample, demonstrating what you did / tried to do? – Michael Zlatkovsky - Microsoft Jun 04 '18 at 20:57
  • Thank you @Michael Zlatkovsky - Microsoft for your reply. I have just added my code in my post. I would like to update my content type fields value with my word addin. Content type fields are from sharepoint document libray. More information could be refered to this link: https://stackoverflow.com/questions/50642434/content-type-fieldscustomxmlparts-document-custom-properties. – balticsunlight Jun 04 '18 at 21:09
  • I just think if it's possible to get a single node, then I can avoid these if statements. And my GDPR value is a radion button with potiential "true" or "false" values. Hope now I have explained clearly. – balticsunlight Jun 04 '18 at 21:14

2 Answers2

1

The correct XPATH format is not an intuitive format, and it does not help that the Microsoft API documentation provide dumb examples that use wildcard (/) xpaths, like so:

xmlPart.getNodesAsync('*', function (nodeResults)

OfficeJS (or perhaps, SharePoint) injects namespace aliases into the mix (ie /ns3:...), so you were on the right track, but to get the 'CGI_Address' SharePoint document property, you need this XPATH syntax:

var xpath = "/ns0:properties[1]/documentManagement[1]/ns3:CGI_Address[1]";
xmlPart.getNodesAsync(xpath, ...);

GOTCHA: When making significant schema changes to the SharePoint content types that the Word document is based on, it may suddenly change the namespace alias from "ns3" to "ns4" or indeed, from "ns4" back to "ns3" like what happened to me today - go figure?!?

And it seems that the OfficeJS API does not properly implement XPATH, as trying to wildcard the namespace alias (so it can accept /ns3 or /ns4 etc) with /*:CGI_Address1 doesn't work. SO Reference (as to why it should work) - how to ignore namespaces with XPath

Ben Mc
  • 139
  • 1
  • 3
  • I just logged in to stack overflow to upvote your answer! Extremely helpful. Just a question when documentation of Microsoft about is too vague. How did you find it? – prashant Jun 29 '21 at 08:15
0

Please use the XPATH expression you send in the xmlPart.getNodesAsync("/", function(nodeResults) method. The first parameter is an XPath expression you can use to get the single node you need.

Juan Balmori
  • 4,898
  • 1
  • 8
  • 17
  • Thank you @Juan Balmori! The thing is my custom XML Parts are auto generated, I have no idea what is the XPath exactly. Would you help out to point out what is my XPAth for the CGI_Address node? Thanks! Please refer to the code below. – balticsunlight Jun 05 '18 at 07:21
  • Göteborg KJKJK 46874985 – balticsunlight Jun 05 '18 at 07:23
  • I learned XML dom today and I noticed I can use xml methods like xmlDoc.getElementByTagName to select a specific node. So problem solved:) Thank you for your help. – balticsunlight Jun 05 '18 at 21:23
  • yes you can also use any XML library to get access to them, but be careful and test it in multiple browsers. (not all libraries are compatible in all browsers) – Juan Balmori Jun 06 '18 at 01:22
  • Hey @Juan Balmori, I still wonder if I don't covert my xml string to dom object, how can I otherwise get a specific node? Like in my code example, I tried ' xmlPart.getNodesAsync('documentManagement/CGI_MainContactPerson' , function (nodeResult) {...}' but the nodeResult I got is 'OSF.DDA.AsyncResult {value: Array(0), status: "succeeded"} status : "succeeded" value:[] __proto__ : Object', this is not what I expected. What should the correct XPath be then? – balticsunlight Jun 06 '18 at 13:10